Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4803b89294 | ||
|
|
e48adbd87d | ||
|
|
227314d83c | ||
|
|
3c0e21eb02 | ||
|
|
86d6153ef1 | ||
|
|
78cf8bded3 | ||
|
|
26d12181cd | ||
|
|
8d184b011c | ||
|
|
ed3a1444ec | ||
|
|
d3e70a47cd | ||
|
|
3171151219 | ||
|
|
e407867635 | ||
|
|
6d9cfab55f | ||
|
|
f0bce029f0 | ||
|
|
d47960a0cf | ||
|
|
8416018afe | ||
|
|
e93fc70169 | ||
|
|
5b3474c781 | ||
|
|
8d2a9f3b2b | ||
|
|
73d09f9b09 | ||
|
|
4e7c6efa2a | ||
|
|
81a884bc61 | ||
|
|
ac4f960352 | ||
|
|
e4b3e4e438 | ||
|
|
d6ee476296 | ||
|
|
c23741ba9a | ||
|
|
7bac5b4740 | ||
|
|
1fe440168e | ||
|
|
26ad57138b | ||
|
|
92e1fdaf0f | ||
|
|
357540d0ad | ||
|
|
405622a91e | ||
|
|
5686c73c56 | ||
|
|
76e2f787ac | ||
|
|
02b67f4e6a | ||
|
|
a2ab527761 | ||
|
|
f1142ae742 | ||
|
|
decb222dac | ||
|
|
00c598e6f7 | ||
|
|
e9843dd3a5 | ||
|
|
37f390742b | ||
|
|
533e7dfd15 | ||
|
|
ddcbe1cd51 | ||
|
|
4eabd04bc6 | ||
|
|
c8f2da6ac9 | ||
|
|
8820ac4bf3 | ||
|
|
236b200f39 | ||
|
|
6789e32674 | ||
|
|
9eb55deedf | ||
|
|
6e76b5b8eb | ||
|
|
491b0da83d | ||
|
|
5d2c17e940 | ||
|
|
0497c4a9e7 | ||
|
|
6d0765848b | ||
|
|
40c4ae71bd | ||
|
|
8edba10dff | ||
|
|
85aa7bc652 | ||
|
|
854ad1db07 | ||
|
|
955600a1e1 | ||
|
|
b739134d85 | ||
|
|
723152566d | ||
|
|
678b045e0e | ||
|
|
681f4df49a | ||
|
|
b19f7d7098 | ||
|
|
daaae3ec10 | ||
|
|
c14957afff | ||
|
|
843a4998f1 | ||
|
|
9637e74edc | ||
|
|
b1bdf4f671 | ||
|
|
238ed8e364 | ||
|
|
8aa1509863 | ||
|
|
aac182e30b | ||
|
|
ac7e953acc | ||
|
|
6ae0f27e05 | ||
|
|
f6e5a92400 | ||
|
|
5e5ff3428c | ||
|
|
1cdbb9c402 | ||
|
|
8caacd1870 | ||
|
|
cfbc4c9c20 | ||
|
|
76dbf1c5d0 | ||
|
|
c0e7c4afa5 | ||
|
|
9da0970d85 | ||
|
|
d6f2ad32a7 | ||
|
|
8dbc87a331 | ||
|
|
77eb1ce44e | ||
|
|
e12f4ae61a | ||
|
|
c23a73625f | ||
|
|
3a66946686 | ||
|
|
7fef43701f | ||
|
|
7f5eb34ac6 | ||
|
|
ba4369f829 | ||
|
|
81af2e51fc | ||
|
|
dff09064c8 | ||
|
|
ee0bb32cce | ||
|
|
4a215c308b | ||
|
|
79493a96ea | ||
|
|
3cca1c4671 | ||
|
|
72e9923d08 | ||
|
|
406e152891 | ||
|
|
e9eb569d50 | ||
|
|
640b389e44 | ||
|
|
314e3349d6 | ||
|
|
0ae4d72bc9 | ||
|
|
8920a5fb21 | ||
|
|
b338ff5dd9 | ||
|
|
87e2fcb37c | ||
|
|
bab43e3b17 | ||
|
|
e602088330 | ||
|
|
2f6db92077 | ||
|
|
cee33c0f77 | ||
|
|
4fcdaa10b6 | ||
|
|
949f74ab04 | ||
|
|
ef68a89b45 | ||
|
|
10ecb35cca | ||
|
|
696ac22f77 | ||
|
|
8d13f98030 | ||
|
|
1dddf13a9d | ||
|
|
855472239a | ||
|
|
dc5d317623 | ||
|
|
91011e9e2a | ||
|
|
bb09b75d3b | ||
|
|
b2f9adad66 | ||
|
|
0c2c84d2a9 | ||
|
|
1733e7cc86 | ||
|
|
831d9a9895 | ||
|
|
70ba3a629d | ||
|
|
29e9702d21 | ||
|
|
f8ef756bd4 | ||
|
|
233b28e8a5 | ||
|
|
da77c17be5 | ||
|
|
8dfa76822e | ||
|
|
4163991b66 | ||
|
|
78323c9a08 | ||
|
|
eb517e86f3 | ||
|
|
e24f3823cb | ||
|
|
fd3e8ee28a | ||
|
|
a980ea7bd6 | ||
|
|
20ce73c54f | ||
|
|
d8f22f7f28 | ||
|
|
591055edaf | ||
|
|
fbf0e06c04 | ||
|
|
9daf327e80 | ||
|
|
4441978e10 | ||
|
|
d8eb770735 | ||
|
|
cefbf79c6e | ||
|
|
fc8762094e | ||
|
|
801c3aadcc | ||
|
|
4296f1ec43 | ||
|
|
a7f469747c | ||
|
|
68d0352343 | ||
|
|
01e6d09f7c | ||
|
|
6582abfd4a | ||
|
|
f8f4b303d7 | ||
|
|
79f05a23a8 | ||
|
|
95845c5c85 | ||
|
|
cd1a24290e | ||
|
|
21261bfb17 | ||
|
|
79abf51cb8 | ||
|
|
e538b837d5 | ||
|
|
7b995e1223 | ||
|
|
c7826b58a3 | ||
|
|
5786dbdb75 | ||
|
|
0f42c19ec7 | ||
|
|
87d44a64f3 | ||
|
|
77dd4ace33 | ||
|
|
0907d71957 | ||
|
|
e7a30646e3 | ||
|
|
98d21b3391 | ||
|
|
35d9203b9c | ||
|
|
e6e384a7f7 | ||
|
|
7d954c14ae | ||
|
|
41388962e2 | ||
|
|
6d51f6b6a9 | ||
|
|
c7af9a3702 | ||
|
|
da7c61202c | ||
|
|
c24e872a33 | ||
|
|
d0809ec313 | ||
|
|
c1a796da38 | ||
|
|
98c27800e0 | ||
|
|
7a18eadd13 | ||
|
|
b07adb7b30 | ||
|
|
4d7c3cce4d | ||
|
|
4ff0ab9cd8 | ||
|
|
264dd50969 | ||
|
|
26d0ad1a6e | ||
|
|
90284018e5 | ||
|
|
46eeec16d4 | ||
|
|
083fb0dccc | ||
|
|
d46f145806 | ||
|
|
868eddfd2b | ||
|
|
8295e6bb5b | ||
|
|
424914b842 | ||
|
|
8c5027df0f | ||
|
|
0b7817d992 | ||
|
|
ca6c9bfd05 | ||
|
|
0a1abd8040 | ||
|
|
ed69a4fdf6 | ||
|
|
2ae19a6d4e | ||
|
|
404bc50dd4 | ||
|
|
cada5eeeaf | ||
|
|
5e9bd40e8b | ||
|
|
0788bab0dd | ||
|
|
4e8e0dbea7 | ||
|
|
b8c5279137 | ||
|
|
a3255b1681 | ||
|
|
f151379f8f | ||
|
|
7784544583 | ||
|
|
f742937296 | ||
|
|
5fd9242291 | ||
|
|
9f343196a9 | ||
|
|
5468eded04 | ||
|
|
1b97758fc9 | ||
|
|
b2e8e49447 | ||
|
|
3eec781139 | ||
|
|
b6f1977fa0 | ||
|
|
e0aa080f00 | ||
|
|
66aa76c836 | ||
|
|
bb9444e1ae | ||
|
|
6c9bfa7755 | ||
|
|
c4fa849290 | ||
|
|
4807e2c410 | ||
|
|
5388efdebc | ||
|
|
1d656de7ba | ||
|
|
eaa1d725a9 | ||
|
|
dea2150d63 | ||
|
|
80f9d6cf75 | ||
|
|
7430d38594 | ||
|
|
6804e4af9f | ||
|
|
138756c31d | ||
|
|
349bc293c6 | ||
|
|
2f87cd10f2 | ||
|
|
fc50eafcca | ||
|
|
b48e20a727 | ||
|
|
ce7ed2e6eb | ||
|
|
043d71e0ff | ||
|
|
1855ae0e1d | ||
|
|
77323a50df | ||
|
|
1c2f6b85ca | ||
|
|
2b5c478e4b | ||
|
|
90fd83a81f | ||
|
|
8fa2a166f3 | ||
|
|
e8cc45ebe7 | ||
|
|
eb87117b91 | ||
|
|
3799dfa1e8 | ||
|
|
163c7fd680 | ||
|
|
44ca762f69 | ||
|
|
8db311ba33 | ||
|
|
99d8604db4 | ||
|
|
90aa88daeb | ||
|
|
ae6eebad4d | ||
|
|
cd31ce1c38 | ||
|
|
ed3846e451 | ||
|
|
0c79cf8e37 | ||
|
|
81c7e16c0e | ||
|
|
16c03095b8 | ||
|
|
b5dab3aa22 | ||
|
|
e4a3c871f8 | ||
|
|
a2fe947b08 | ||
|
|
8df49ecfc1 | ||
|
|
526b9bd4c7 | ||
|
|
c67ff3d936 | ||
|
|
417b17da98 | ||
|
|
4ca19a4eb0 | ||
|
|
e834dfb7ee | ||
|
|
5e1ff74fb3 | ||
|
|
7a1d0f2ca7 | ||
|
|
b305522106 | ||
|
|
ff3495645a | ||
|
|
ddc000321f | ||
|
|
fe4e6af3b9 | ||
|
|
a1a83cc32c | ||
|
|
e37665218b | ||
|
|
2a876f4136 | ||
|
|
290d8e8a64 | ||
|
|
121bce529f | ||
|
|
1232d98573 | ||
|
|
208d9150b0 | ||
|
|
351bf7725e | ||
|
|
a547776766 | ||
|
|
86a8d20757 | ||
|
|
760c420f95 | ||
|
|
44c2edf58e | ||
|
|
e88207c232 | ||
|
|
f6b2450fcd | ||
|
|
a124ecd3ed | ||
|
|
34fcc3d29e | ||
|
|
5f3011eebc | ||
|
|
d4464edb6c | ||
|
|
1dc89a80db | ||
|
|
bd23599770 | ||
|
|
bda6ff80da | ||
|
|
16bee9825f | ||
|
|
5e4a4c4e8f | ||
|
|
0a03093333 | ||
|
|
960b1d53f7 | ||
|
|
f09dee6a52 | ||
|
|
301e1e56d1 | ||
|
|
6b2dbd382d | ||
|
|
e6f526c766 | ||
|
|
06cca669a0 | ||
|
|
f89ccea208 | ||
|
|
0728f2d995 | ||
|
|
c7a7a61c9a | ||
|
|
aca11e66a8 | ||
|
|
46c7a001c2 | ||
|
|
d6aa3c50a3 | ||
|
|
caaadc5cf3 | ||
|
|
14d703903c | ||
|
|
76fa14ab01 | ||
|
|
d1afe255e5 | ||
|
|
8f27739331 | ||
|
|
7a6aba5a2a | ||
|
|
ca0ec1f99d | ||
|
|
4e167486a1 | ||
|
|
503bbcd995 | ||
|
|
b160d2f634 | ||
|
|
2e7628a837 | ||
|
|
1259948ed7 | ||
|
|
81881ae1a4 | ||
|
|
0b5c581aca | ||
|
|
eb3614ed0c | ||
|
|
eb50513277 | ||
|
|
c3af73b8cf | ||
|
|
b552164a13 | ||
|
|
b6dc9ecadb | ||
|
|
0723dc8dbb | ||
|
|
0b1fffb5bf | ||
|
|
a39d87e5c5 | ||
|
|
0b0c3310cf | ||
|
|
f75c3750a5 | ||
|
|
3da760721b | ||
|
|
a9ad3feeec | ||
|
|
479c4ade67 | ||
|
|
84afa3e714 | ||
|
|
9a69665bab | ||
|
|
fea34ee937 | ||
|
|
ff2412c65d | ||
|
|
658953860a | ||
|
|
b473783527 | ||
|
|
7e590d4925 | ||
|
|
232fd3e2f2 | ||
|
|
9ea25fb77c | ||
|
|
6c47136de3 | ||
|
|
6fae29b488 | ||
|
|
7ed8cc9380 | ||
|
|
142e9d1028 | ||
|
|
c96c30ff9a | ||
|
|
337f1cc100 | ||
|
|
c3cb89dbea | ||
|
|
445bd1f668 | ||
|
|
1bded908c1 | ||
|
|
8d9dea4b08 | ||
|
|
4e98d6d8ce | ||
|
|
55b5cd939e | ||
|
|
d72f5a43c8 | ||
|
|
b406d8d30b | ||
|
|
f9c91c9ba0 | ||
|
|
0213d7eeb4 | ||
|
|
048c5c0970 | ||
|
|
728542fce8 | ||
|
|
81ca24c7a2 | ||
|
|
32ec272253 | ||
|
|
758982b660 | ||
|
|
a83bba10e3 | ||
|
|
4b9342fa8b | ||
|
|
a48162cf4a | ||
|
|
3fa61e777c | ||
|
|
01a2c55207 | ||
|
|
1a2376e6b7 | ||
|
|
dab0d6a47f | ||
|
|
b5d90b5cb7 | ||
|
|
25fd0bd2af | ||
|
|
a4bb63fcd4 | ||
|
|
9d85785c27 | ||
|
|
4206242627 | ||
|
|
f0149be9ad | ||
|
|
5d56a1f0e0 | ||
|
|
ad06c75058 | ||
|
|
d5b6e17e59 | ||
|
|
ffe2514e11 | ||
|
|
8621bed5d4 | ||
|
|
634031e6dc | ||
|
|
11fae36469 | ||
|
|
3d01e36a71 | ||
|
|
c2082b1ac5 | ||
|
|
c94bbf84fe | ||
|
|
930363cd3f | ||
|
|
085ca9eb58 | ||
|
|
f486d44804 | ||
|
|
1b4fbd3449 | ||
|
|
43ad7bf646 | ||
|
|
64921c3308 | ||
|
|
7a0e6a00c5 | ||
|
|
1332dd2c0e | ||
|
|
d52628bed2 | ||
|
|
981ec006b2 | ||
|
|
7da05cf678 | ||
|
|
316882bcd0 | ||
|
|
b204e52297 | ||
|
|
f82a63f4c8 | ||
|
|
cb0f2108a4 | ||
|
|
300b7a7a68 | ||
|
|
c3852ca60d | ||
|
|
a5fb735c93 | ||
|
|
d0b04ba84f | ||
|
|
9552742a39 | ||
|
|
8e9bdf6c0c | ||
|
|
818cc48502 | ||
|
|
adc4e28eb8 | ||
|
|
2e3a4d3bf1 | ||
|
|
d9bcac78e7 | ||
|
|
2342947849 | ||
|
|
19204dee8d | ||
|
|
863fa90b80 | ||
|
|
6fdef4a8f1 | ||
|
|
9469ceaa02 | ||
|
|
857f184409 | ||
|
|
a2f4a725f5 | ||
|
|
d12449bbb9 | ||
|
|
a41f4711dd | ||
|
|
3c2b018d49 | ||
|
|
e221a09709 | ||
|
|
26ff4bd843 | ||
|
|
d8e28f384a | ||
|
|
65e68c3cc4 | ||
|
|
7b76ab2a59 | ||
|
|
ae2a01b463 | ||
|
|
cda022a9f4 | ||
|
|
672e48c5f8 | ||
|
|
6fbdb1354f | ||
|
|
79bc7fd443 | ||
|
|
5578dd3339 | ||
|
|
0232dbd196 | ||
|
|
d44e192eaa | ||
|
|
4f12b19cf8 | ||
|
|
392ac1b1c7 | ||
|
|
8ad175aca3 | ||
|
|
6afa58c42b | ||
|
|
8be03cf232 | ||
|
|
23ea53d3ff | ||
|
|
294f40e7ac | ||
|
|
4f5f706ee5 | ||
|
|
27c1a7b4e4 | ||
|
|
cfaa5be6d7 | ||
|
|
a6942280a0 | ||
|
|
159124e6a3 | ||
|
|
6e63293a3c | ||
|
|
9a9dc0d788 | ||
|
|
e201cd074c | ||
|
|
0fd49a6e1c | ||
|
|
6169a85464 | ||
|
|
e583344fee | ||
|
|
dcee00394c | ||
|
|
e48dc99dc0 | ||
|
|
3ba3dda384 | ||
|
|
bbf1ce993c | ||
|
|
56245a8c9b | ||
|
|
4f2e65094c | ||
|
|
0bf456cbc8 | ||
|
|
9213d0da16 | ||
|
|
13f2ece0ff | ||
|
|
45c2a74c94 | ||
|
|
b1b3e90e9b | ||
|
|
90ef841dae | ||
|
|
b46000e8eb | ||
|
|
b24891355d | ||
|
|
14bde5a790 | ||
|
|
d6445f17e3 | ||
|
|
6124c3fe40 | ||
|
|
5531a4b194 | ||
|
|
839a0bbd42 | ||
|
|
1ba6272e4e | ||
|
|
fdd86815ef | ||
|
|
c8091fdc84 |
No files matched your search
@@ -1,34 +0,0 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
:: Check for permissions
|
||||
>nul 2>&1 "%SYSTEMROOT%\system32\icacls.exe" "%SYSTEMROOT%\system32\config\system"
|
||||
|
||||
if %errorlevel% NEQ 0 goto NoAdmin
|
||||
goto gotAdmin
|
||||
|
||||
:NoAdmin
|
||||
echo You do not have administrator rights, please run this script as administrator.
|
||||
pause
|
||||
exit /B
|
||||
|
||||
:gotAdmin
|
||||
if exist "%temp%\getadmin.vbs" del "%temp%\getadmin.vbs"
|
||||
|
||||
set "script_dir=%~dp0"
|
||||
set "script_dir=%script_dir:~0,-1%"
|
||||
|
||||
bcdedit -debug on
|
||||
bcdedit /set testsigning on
|
||||
bcdedit /deletevalue {current} safeboot
|
||||
|
||||
powershell.exe -ExecutionPolicy Bypass -Command ^
|
||||
"$endDate = (Get-Date).AddYears(100); ^
|
||||
$cert = New-SelfSignedCertificate -DnsName PYAS -CertStoreLocation cert:\LocalMachine\My -Type CodeSigning -NotAfter $endDate; ^
|
||||
$pwd = ConvertTo-SecureString -String 'PYAS' -Force -AsPlainText; ^
|
||||
Export-PfxCertificate -Cert $cert -FilePath '%script_dir%\PYAS.pfx' -Password $pwd;"
|
||||
"%script_dir%\signtool.exe" sign /f "%script_dir%\PYAS.pfx" /p PYAS "%script_dir%\PYAS_Driver.sys"
|
||||
sc create PYAS_Driver type= kernel start= demand binPath= "%script_dir%\PYAS_Driver.sys"
|
||||
|
||||
shutdown -r -t 0
|
||||
endlocal
|
||||
Whitespace-only changes.
Binary file not shown.
@@ -1,25 +0,0 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
:: Check for permissions
|
||||
>nul 2>&1 "%SYSTEMROOT%\system32\icacls.exe" "%SYSTEMROOT%\system32\config\system"
|
||||
|
||||
if %errorlevel% NEQ 0 goto NoAdmin
|
||||
goto gotAdmin
|
||||
|
||||
:NoAdmin
|
||||
echo You do not have administrator rights, please run this script as administrator.
|
||||
pause
|
||||
exit /B
|
||||
|
||||
:gotAdmin
|
||||
if exist "%temp%\getadmin.vbs" del "%temp%\getadmin.vbs"
|
||||
|
||||
sc stop PYAS_Driver
|
||||
sc delete PYAS_Driver
|
||||
|
||||
bcdedit /set testsigning off
|
||||
bcdedit -debug off
|
||||
|
||||
shutdown -r -t 0
|
||||
endlocal
|
||||
Binary file not shown.
@@ -1,8 +1,8 @@
|
||||
import "pe"
|
||||
|
||||
rule PYAS_Rules_A_1 {
|
||||
rule General_1 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_1"
|
||||
description = "1"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -57,9 +57,9 @@ rule PYAS_Rules_A_1 {
|
||||
1 of ($x*) and 8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_2 {
|
||||
rule General_2 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_2"
|
||||
description = "2"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -82,9 +82,9 @@ rule PYAS_Rules_A_2 {
|
||||
8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_3 {
|
||||
rule General_3 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_3"
|
||||
description = "3"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -106,7 +106,7 @@ rule PYAS_Rules_A_3 {
|
||||
$x1 and 8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_4 {
|
||||
rule General_4 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A4"
|
||||
author = "PYAS Security"
|
||||
@@ -124,9 +124,9 @@ rule PYAS_Rules_A_4 {
|
||||
($x1 and $x2) and 5 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_5 {
|
||||
rule General_5 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_5"
|
||||
description = "5"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -147,9 +147,9 @@ rule PYAS_Rules_A_5 {
|
||||
$x1 and 3 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_6 {
|
||||
rule General_6 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_6"
|
||||
description = "6"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -214,9 +214,9 @@ rule PYAS_Rules_A_6 {
|
||||
1 of ($x*) and 5 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_7 {
|
||||
rule General_7 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_462"
|
||||
description = "7"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -247,9 +247,9 @@ rule PYAS_Rules_A_7 {
|
||||
10 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_8 {
|
||||
rule General_8 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_8"
|
||||
description = "8"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -278,9 +278,9 @@ rule PYAS_Rules_A_8 {
|
||||
2 of ($x*) and 6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_9 {
|
||||
rule General_9 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_9"
|
||||
description = "9"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -303,9 +303,9 @@ rule PYAS_Rules_A_9 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_10 {
|
||||
rule General_10 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_10"
|
||||
description = "10"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -329,9 +329,9 @@ rule PYAS_Rules_A_10 {
|
||||
($x1 and $x2) and 6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_11 {
|
||||
rule General_11 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_11"
|
||||
description = "11"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -349,9 +349,9 @@ rule PYAS_Rules_A_11 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_12 {
|
||||
rule General_12 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_12"
|
||||
description = "12"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -376,9 +376,9 @@ rule PYAS_Rules_A_12 {
|
||||
1 of ($x*) and 5 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_13 {
|
||||
rule General_13 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_13"
|
||||
description = "13"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -404,9 +404,9 @@ rule PYAS_Rules_A_13 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_14 {
|
||||
rule General_14 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_14"
|
||||
description = "14"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -430,9 +430,9 @@ rule PYAS_Rules_A_14 {
|
||||
8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_15 {
|
||||
rule General_15 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_15"
|
||||
description = "15"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -459,9 +459,9 @@ rule PYAS_Rules_A_15 {
|
||||
8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_16 {
|
||||
rule General_16 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_16"
|
||||
description = "16"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -485,9 +485,9 @@ rule PYAS_Rules_A_16 {
|
||||
($x1 and $x2) and 6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_17 {
|
||||
rule General_17 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_17"
|
||||
description = "17"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -508,9 +508,9 @@ rule PYAS_Rules_A_17 {
|
||||
$x1 and 8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_18 {
|
||||
rule General_18 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_18"
|
||||
description = "18"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -531,9 +531,9 @@ rule PYAS_Rules_A_18 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_19 {
|
||||
rule General_19 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_19"
|
||||
description = "19"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -560,9 +560,9 @@ rule PYAS_Rules_A_19 {
|
||||
($x1 and $x2) and 8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_20 {
|
||||
rule General_20 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_20"
|
||||
description = "20"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -589,9 +589,9 @@ rule PYAS_Rules_A_20 {
|
||||
8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_21 {
|
||||
rule General_21 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_21"
|
||||
description = "21"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -616,9 +616,9 @@ rule PYAS_Rules_A_21 {
|
||||
8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_22 {
|
||||
rule General_22 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_22"
|
||||
description = "22"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -635,10 +635,9 @@ rule PYAS_Rules_A_22 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
import "pe"
|
||||
rule PYAS_Rules_A_23 {
|
||||
rule General_23 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_23"
|
||||
description = "23"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -658,10 +657,9 @@ rule PYAS_Rules_A_23 {
|
||||
7 of them
|
||||
}
|
||||
|
||||
import "pe"
|
||||
rule PYAS_Rules_A_24 {
|
||||
rule General_24 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_24"
|
||||
description = "24"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -688,9 +686,9 @@ rule PYAS_Rules_A_24 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_25 {
|
||||
rule General_25 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_25"
|
||||
description = "25"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -716,9 +714,9 @@ rule PYAS_Rules_A_25 {
|
||||
$x1 and 5 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_26 {
|
||||
rule General_26 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_26"
|
||||
description = "26"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -742,9 +740,9 @@ rule PYAS_Rules_A_26 {
|
||||
8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_27 {
|
||||
rule General_27 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_27"
|
||||
description = "27"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -768,42 +766,37 @@ rule PYAS_Rules_A_27 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_28 {
|
||||
rule General_28 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_28"
|
||||
description = "28"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
$s1 = "GNU C11 6.3.0" ascii
|
||||
$s2 = "GCC: (MinGW.org GCC-6.3.0-1) 6.3.0" fullword ascii
|
||||
$s3 = "___mingw_readdir" fullword ascii
|
||||
$s4 = "___mingw_closedir" fullword ascii
|
||||
$s5 = "___mingw_seekdir" fullword ascii
|
||||
$s6 = "%d is not a prime number." fullword ascii
|
||||
$s7 = "___mingw_rewinddir" fullword ascii
|
||||
$s8 = "__mingw32_init_mainargs" fullword ascii
|
||||
$s9 = "___mingw_telldir" fullword ascii
|
||||
$s10 = "Enter an integer: " fullword ascii
|
||||
$s11 = "___mingw_opendir" fullword ascii
|
||||
$s12 = "/home/keith/" ascii
|
||||
$s13 = "../../../src/gcc-6.3.0/libgcc" ascii
|
||||
$s14 = "___mingw_dirname" fullword ascii
|
||||
$s15 = "_isPrime`" fullword ascii
|
||||
$s16 = "%d is a prime number." fullword ascii
|
||||
$s17 = ".weak.__Jv_RegisterClasses.___EH_FRAME_BEGIN__" fullword ascii
|
||||
$s18 = "-mtune=generic" ascii
|
||||
$s19 = "-march=i586" ascii
|
||||
$s20 = "-g -g -g -O2 -O2 -O2" ascii
|
||||
$s21 = "-fbuilding-libgcc" ascii
|
||||
$s22 = "-fno-stack-protector" ascii
|
||||
$x1 = "schemas.microsoft.com" wide
|
||||
$x2 = "Client Worker Thread" ascii
|
||||
$s1 = "A6BFEA43-501F-456F-A845-983D3AD7B8F0" wide
|
||||
$s2 = "upgrader" wide
|
||||
$s3 = "rtvscan.exe" wide
|
||||
$s4 = "Enable-WindowsOptionalFeature -FeatureName" wide
|
||||
$s5 = "remupd.exe" fullword wide
|
||||
$s6 = "Mcshield.exe" fullword wide
|
||||
$s7 = "mssecess.exe" fullword wide
|
||||
$s8 = "RavMonD.exe" fullword wide
|
||||
$s9 = "KvMonXP.exe" fullword wide
|
||||
$s10 = "baiduSafeTray.exe" fullword wide
|
||||
$s11 = "Qavanijeb.exe" fullword wide
|
||||
$s12 = "%s --> Error: %d, EC: %d" fullword ascii
|
||||
$s13 = "wscript.exe //E:vbscript" wide
|
||||
$s14 = "upgrader_64" wide
|
||||
$s15 = "Process Data Error" fullword wide
|
||||
condition:
|
||||
uint16(0) == 0x5a4d and filesize < 500KB and
|
||||
8 of them
|
||||
uint16(0) == 0x5a4d and filesize < 1000KB and
|
||||
1 of ($x*) and 6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_29 {
|
||||
rule General_29 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_29"
|
||||
description = "29"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -837,9 +830,9 @@ rule PYAS_Rules_A_29 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_30 {
|
||||
rule General_30 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_30"
|
||||
description = "30"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -858,9 +851,9 @@ rule PYAS_Rules_A_30 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_31 {
|
||||
rule General_31 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_31"
|
||||
description = "31"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -878,9 +871,9 @@ rule PYAS_Rules_A_31 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_32 {
|
||||
rule General_32 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_32"
|
||||
description = "32"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -909,9 +902,9 @@ rule PYAS_Rules_A_32 {
|
||||
$x1 and 8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_33 {
|
||||
rule General_33 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_33"
|
||||
description = "33"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -937,9 +930,9 @@ rule PYAS_Rules_A_33 {
|
||||
$x1 and 8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_34 {
|
||||
rule General_34 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_30"
|
||||
description = "34"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -965,9 +958,9 @@ rule PYAS_Rules_A_34 {
|
||||
8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_35 {
|
||||
rule General_35 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_35"
|
||||
description = "35"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -996,9 +989,9 @@ rule PYAS_Rules_A_35 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_36 {
|
||||
rule General_36 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_36"
|
||||
description = "36"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1023,9 +1016,9 @@ rule PYAS_Rules_A_36 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_37 {
|
||||
rule General_37 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_37"
|
||||
description = "37"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1053,9 +1046,9 @@ rule PYAS_Rules_A_37 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_38 {
|
||||
rule General_38 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_38"
|
||||
description = "38"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1083,9 +1076,9 @@ rule PYAS_Rules_A_38 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_39 {
|
||||
rule General_39 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_39"
|
||||
description = "39"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1104,9 +1097,9 @@ rule PYAS_Rules_A_39 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_40 {
|
||||
rule General_40 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_40"
|
||||
description = "40"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1136,9 +1129,9 @@ rule PYAS_Rules_A_40 {
|
||||
8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_41 {
|
||||
rule General_41 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_41"
|
||||
description = "41"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1160,9 +1153,9 @@ rule PYAS_Rules_A_41 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_42 {
|
||||
rule General_42 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_42"
|
||||
description = "42"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1182,9 +1175,9 @@ rule PYAS_Rules_A_42 {
|
||||
6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_43 {
|
||||
rule General_43 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_43"
|
||||
description = "43"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1209,9 +1202,9 @@ rule PYAS_Rules_A_43 {
|
||||
8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_44 {
|
||||
rule General_44 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_44"
|
||||
description = "44"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1239,9 +1232,9 @@ rule PYAS_Rules_A_44 {
|
||||
8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_45 {
|
||||
rule General_45 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_45"
|
||||
description = "45"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1268,9 +1261,9 @@ rule PYAS_Rules_A_45 {
|
||||
8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_46 {
|
||||
rule General_46 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_46"
|
||||
description = "46"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1298,9 +1291,9 @@ rule PYAS_Rules_A_46 {
|
||||
$x1 and 8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_47 {
|
||||
rule General_47 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_47"
|
||||
description = "47"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1329,9 +1322,9 @@ rule PYAS_Rules_A_47 {
|
||||
1 of ($x*) and 5 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_48 {
|
||||
rule General_48 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_48"
|
||||
description = "48"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1350,9 +1343,9 @@ rule PYAS_Rules_A_48 {
|
||||
2 of ($x*) and 6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_49 {
|
||||
rule General_49 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_49"
|
||||
description = "49"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1378,9 +1371,9 @@ rule PYAS_Rules_A_49 {
|
||||
3 of ($x*) and 5 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_50 {
|
||||
rule General_50 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_50"
|
||||
description = "50"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1400,9 +1393,9 @@ rule PYAS_Rules_A_50 {
|
||||
$x1 and 6 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_51 {
|
||||
rule General_51 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_51"
|
||||
description = "51"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
@@ -1420,9 +1413,9 @@ rule PYAS_Rules_A_51 {
|
||||
1 of ($x*) and 4 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_52 {
|
||||
rule General_52 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_52"
|
||||
description = "52"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-13"
|
||||
strings:
|
||||
@@ -1444,31 +1437,3 @@ rule PYAS_Rules_A_52 {
|
||||
uint16(0) == 0x5a4d and filesize < 2000KB and
|
||||
8 of them
|
||||
}
|
||||
|
||||
rule PYAS_Rules_A_53 {
|
||||
meta:
|
||||
description = "PYAS_Rules_A_53"
|
||||
author = "PYAS Security"
|
||||
date = "2024-06-12"
|
||||
strings:
|
||||
$x1 = "schemas.microsoft.com" wide
|
||||
$x2 = "Client Worker Thread" ascii
|
||||
$s1 = "A6BFEA43-501F-456F-A845-983D3AD7B8F0" wide
|
||||
$s2 = "upgrader" wide
|
||||
$s3 = "rtvscan.exe" wide
|
||||
$s4 = "Enable-WindowsOptionalFeature -FeatureName" wide
|
||||
$s5 = "remupd.exe" fullword wide
|
||||
$s6 = "Mcshield.exe" fullword wide
|
||||
$s7 = "mssecess.exe" fullword wide
|
||||
$s8 = "RavMonD.exe" fullword wide
|
||||
$s9 = "KvMonXP.exe" fullword wide
|
||||
$s10 = "baiduSafeTray.exe" fullword wide
|
||||
$s11 = "Qavanijeb.exe" fullword wide
|
||||
$s12 = "%s --> Error: %d, EC: %d" fullword ascii
|
||||
$s13 = "wscript.exe //E:vbscript" wide
|
||||
$s14 = "upgrader_64" wide
|
||||
$s15 = "Process Data Error" fullword wide
|
||||
condition:
|
||||
uint16(0) == 0x5a4d and filesize < 1000KB and
|
||||
1 of ($x*) and 6 of them
|
||||
}
|
||||
@@ -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')
|
||||
@@ -0,0 +1,34 @@
|
||||
import os, hashlib
|
||||
|
||||
####################################################################################################
|
||||
|
||||
def calc_sha256(path):
|
||||
with open(path, "rb") as f:
|
||||
return hashlib.sha256(f.read()).digest()
|
||||
|
||||
def dedup_realtime(root):
|
||||
seen = set()
|
||||
deleted = 0
|
||||
for dirpath, _, files in os.walk(root):
|
||||
for name in files:
|
||||
p = os.path.join(dirpath, name)
|
||||
try:
|
||||
h = calc_sha256(p)
|
||||
except Exception:
|
||||
continue
|
||||
if h in seen:
|
||||
try:
|
||||
os.remove(p)
|
||||
print(p)
|
||||
deleted += 1
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
seen.add(h)
|
||||
print(f"deleted {deleted}")
|
||||
|
||||
####################################################################################################
|
||||
|
||||
if __name__ == "__main__":
|
||||
dedup_realtime(input("Input file path: "))
|
||||
input('Deduplicate Complete')
|
||||
@@ -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')
|
||||
@@ -0,0 +1,721 @@
|
||||
import os, sys, time, ctypes, sqlite3, datetime, pefile, math, hashlib
|
||||
import numpy as np
|
||||
import ctypes.wintypes
|
||||
|
||||
####################################################################################################
|
||||
|
||||
DB_PATH = "pe_features.db"
|
||||
BATCH_SIZE = 1000
|
||||
MAX_FILE_SIZE = 256 * 1024 * 1024
|
||||
TARGET_EXTENSIONS = {
|
||||
'.exe', '.dll', '.sys', '.ocx', '.scr', '.efi', '.acm', '.ax', '.cpl', '.drv', '.com', '.mui', '.pyd'
|
||||
}
|
||||
|
||||
####################################################################################################
|
||||
|
||||
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_UNION(ctypes.Union):
|
||||
_fields_ = [
|
||||
("pFile", ctypes.POINTER(WINTRUST_FILE_INFO)),
|
||||
("pCatalog", ctypes.wintypes.LPVOID),
|
||||
("pBlob", ctypes.wintypes.LPVOID),
|
||||
("pSgnr", ctypes.wintypes.LPVOID),
|
||||
("pCert", 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),
|
||||
("u", WINTRUST_DATA_UNION),
|
||||
("dwStateAction", ctypes.wintypes.DWORD),
|
||||
("hWVTStateData", ctypes.wintypes.HANDLE),
|
||||
("pwszURLReference", ctypes.wintypes.LPCWSTR),
|
||||
("dwProvFlags", ctypes.wintypes.DWORD),
|
||||
("dwUIContext", ctypes.wintypes.DWORD),
|
||||
("pSignatureSettings", ctypes.wintypes.LPVOID)
|
||||
]
|
||||
|
||||
class GUID(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("Data1", ctypes.wintypes.DWORD),
|
||||
("Data2", ctypes.wintypes.WORD),
|
||||
("Data3", ctypes.wintypes.WORD),
|
||||
("Data4", ctypes.c_ubyte * 8)
|
||||
]
|
||||
|
||||
V2_GUID = GUID(0x00AAC56B, 0xCD44, 0x11D0, (ctypes.c_ubyte * 8)(0x8C, 0xC2, 0x00, 0xC0, 0x4F, 0xC2, 0x95, 0xEE))
|
||||
|
||||
####################################################################################################
|
||||
|
||||
def verify_signature(file_path):
|
||||
if os.name != 'nt':
|
||||
return 0
|
||||
try:
|
||||
wintrust = ctypes.windll.wintrust
|
||||
wintrust.WinVerifyTrust.argtypes = [ctypes.wintypes.HWND, ctypes.POINTER(GUID), ctypes.wintypes.LPVOID]
|
||||
wintrust.WinVerifyTrust.restype = ctypes.wintypes.LONG
|
||||
|
||||
abs_path = os.path.abspath(file_path)
|
||||
|
||||
fi = WINTRUST_FILE_INFO()
|
||||
fi.cbStruct = ctypes.sizeof(WINTRUST_FILE_INFO)
|
||||
fi.pcwszFilePath = abs_path
|
||||
fi.hFile = None
|
||||
fi.pgKnownSubject = None
|
||||
|
||||
wt_union = WINTRUST_DATA_UNION()
|
||||
wt_union.pFile = ctypes.pointer(fi)
|
||||
|
||||
td = WINTRUST_DATA()
|
||||
td.cbStruct = ctypes.sizeof(WINTRUST_DATA)
|
||||
td.pPolicyCallbackData = None
|
||||
td.pSIPClientData = None
|
||||
td.dwUIChoice = 2
|
||||
td.fdwRevocationChecks = 0
|
||||
td.dwUnionChoice = 1
|
||||
td.u = wt_union
|
||||
td.dwStateAction = 0
|
||||
td.hWVTStateData = None
|
||||
td.pwszURLReference = None
|
||||
td.dwProvFlags = 0
|
||||
td.dwUIContext = 0
|
||||
td.pSignatureSettings = None
|
||||
|
||||
return 1 if wintrust.WinVerifyTrust(None, ctypes.byref(V2_GUID), ctypes.byref(td)) == 0 else 0
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return 0
|
||||
|
||||
####################################################################################################
|
||||
|
||||
class Features:
|
||||
API_CAT_MAPPING = {
|
||||
'ProcessControl': {
|
||||
'CreateProcessA', 'CreateProcessW', 'WinExec', 'ShellExecuteA', 'ShellExecuteW',
|
||||
'ShellExecuteExW', 'ExitProcess', 'TerminateProcess', 'OpenProcess', 'GetExitCodeProcess',
|
||||
'SetThreadPriority', 'GetThreadPriority', 'GetCurrentProcess', 'GetCurrentProcessId',
|
||||
'GetModuleFileNameA', 'GetCommandLineA', 'GetModuleFileNameW', 'GetStartupInfoW'
|
||||
},
|
||||
'Injection': {
|
||||
'VirtualAlloc', 'VirtualAllocEx', 'VirtualProtect', 'VirtualProtectEx', 'WriteProcessMemory',
|
||||
'ReadProcessMemory', 'CreateRemoteThread', 'QueueUserAPC', 'SetThreadContext', 'GetThreadContext',
|
||||
'Wow64SetThreadContext', 'NtUnmapViewOfSection', 'ZwUnmapViewOfSection', 'RtlCreateUserThread',
|
||||
'SetWindowsHookExA', 'SetWindowsHookExW', 'UnhookWindowsHookEx', 'LoadLibraryA', 'LoadLibraryW',
|
||||
'LoadLibraryExA', 'LoadLibraryExW', 'GetProcAddress', 'GetModuleHandleA', 'GetModuleHandleW',
|
||||
'FreeLibrary', 'CreateFileMappingA', 'CreateFileMappingW', 'MapViewOfFile', 'UnmapViewOfSection',
|
||||
'VirtualFree', 'VirtualQuery'
|
||||
},
|
||||
'Synchronization': {
|
||||
'WaitForSingleObject', 'WaitForSingleObjectEx', 'WaitForMultipleObjects', 'WaitForMultipleObjectsEx',
|
||||
'CreateMutexA', 'CreateMutexW', 'OpenMutexW', 'ReleaseMutex', 'CreateEventA', 'CreateEventW',
|
||||
'OpenEventW', 'SetEvent', 'ResetEvent', 'EnterCriticalSection', 'LeaveCriticalSection',
|
||||
'InitializeCriticalSection', 'DeleteCriticalSection', 'Sleep', 'SleepEx',
|
||||
'InitializeCriticalSectionAndSpinCount', 'InterlockedDecrement', 'InterlockedIncrement',
|
||||
'InterlockedExchange', 'InterlockedCompareExchange', 'SetTimer', 'KillTimer'
|
||||
},
|
||||
'MultiThreading': {
|
||||
'CreateThread', 'ResumeThread', 'SuspendThread', 'ExitThread', 'TerminateThread',
|
||||
'GetCurrentThread', 'GetCurrentThreadId', 'TlsAlloc', 'TlsSetValue', 'TlsGetValue',
|
||||
'CreateThreadpoolWork', 'SubmitThreadpoolWork', 'TlsFree'
|
||||
},
|
||||
'Network': {
|
||||
'socket', 'connect', 'send', 'recv', 'bind', 'listen', 'accept', 'gethostbyname', 'getaddrinfo',
|
||||
'WSAStartup', 'WSACleanup', 'WSAIoctl', 'WSASocketA', 'WSASocketW', 'closesocket', 'htons',
|
||||
'InternetOpenA', 'InternetOpenW', 'InternetConnectA', 'InternetConnectW', 'InternetOpenUrlA',
|
||||
'InternetOpenUrlW', 'HttpOpenRequestA', 'HttpOpenRequestW', 'HttpSendRequestA', 'HttpSendRequestW',
|
||||
'InternetReadFile', 'URLDownloadToFileA', 'URLDownloadToFileW', 'DnsQuery_A', 'DnsQuery_W'
|
||||
},
|
||||
'Encryption': {
|
||||
'CryptAcquireContextA', 'CryptAcquireContextW', 'CryptCreateHash', 'CryptHashData',
|
||||
'CryptDeriveKey', 'CryptEncrypt', 'CryptDecrypt', 'CryptDestroyKey', 'CryptDestroyHash',
|
||||
'CryptReleaseContext', 'CryptGenKey', 'CryptImportKey', 'CryptExportKey'
|
||||
},
|
||||
'DataObfuscation': {
|
||||
'RtlDecompressBuffer', 'MultiByteToWideChar', 'WideCharToMultiByte', 'Base64Decode',
|
||||
'CryptDecodeObject', 'IsDBCSLeadByte', 'CharUpperA', 'CharLowerA',
|
||||
'GetStringTypeW', 'LCMapStringW', 'IsValidCodePage', 'DecodePointer', 'EncodePointer'
|
||||
},
|
||||
'FileIO': {
|
||||
'CreateFileA', 'CreateFileW', 'WriteFile', 'ReadFile', 'DeleteFileA', 'DeleteFileW',
|
||||
'CopyFileA', 'CopyFileW', 'MoveFileA', 'MoveFileW', 'FindFirstFileA', 'FindNextFileA',
|
||||
'GetTempPathA', 'GetTempPathW', 'GetTempFileNameA', 'GetTempFileNameW', 'SetFileAttributesA',
|
||||
'SetFileAttributesW', 'DeviceIoControl', 'SetFileTime', 'GetFileSize', 'GetFileSizeEx',
|
||||
'SetFilePointer', 'FlushFileBuffers', 'ConnectNamedPipe', 'PeekNamedPipe',
|
||||
'CloseHandle', 'GetFileType', 'SetStdHandle', 'SetFilePointerEx', 'FindClose',
|
||||
'SetHandleCount', 'SetEndOfFile', 'GetFullPathNameA', 'GetFileAttributesA'
|
||||
},
|
||||
'Registry': {
|
||||
'RegOpenKeyExA', 'RegOpenKeyExW', 'RegSetValueExA', 'RegSetValueExW',
|
||||
'RegCreateKeyExA', 'RegCreateKeyExW', 'RegDeleteKeyA', 'RegDeleteKeyW',
|
||||
'RegEnumValueA', 'RegEnumValueW', 'RegQueryValueExA', 'RegQueryValueExW',
|
||||
'RegDeleteValueA', 'RegDeleteValueW', 'RegCloseKey'
|
||||
},
|
||||
'Services': {
|
||||
'OpenSCManagerA', 'OpenSCManagerW', 'CreateServiceA', 'CreateServiceW',
|
||||
'StartServiceA', 'StartServiceW', 'ControlService', 'DeleteService'
|
||||
},
|
||||
'Privileges': {
|
||||
'AdjustTokenPrivileges', 'LookupPrivilegeValueA', 'LookupPrivilegeValueW',
|
||||
'OpenProcessToken', 'NetUserAdd', 'NetLocalGroupAddMembers', 'IsAdmin',
|
||||
'GetUserNameA', 'GetUserNameW'
|
||||
},
|
||||
'Native': {
|
||||
'RtlUnwind', 'RtlVirtualUnwind', 'RtlCaptureContext', 'RtlLookupFunctionEntry',
|
||||
'NtClose', 'NtQueryInformationProcess', 'RtlAllocateHeap', 'RtlFreeHeap',
|
||||
'GetSystemTimeAsFileTime', 'GetLocalTime', 'GlobalMemoryStatus',
|
||||
'GetVersionExA', 'GetVersionExW', 'GetComputerNameA', 'GetComputerNameW',
|
||||
'GetLastError', 'GetACP', 'RaiseException', 'SetLastError', 'GetEnvironmentStringsW',
|
||||
'FreeEnvironmentStringsW', 'GetLocaleInfoA', 'lstrlenA', 'GetVersion', 'GetSystemInfo',
|
||||
'CompareStringA'
|
||||
},
|
||||
'DotNet': {
|
||||
'_CorExeMain', '_CorDllMain'
|
||||
},
|
||||
'AntiDebug': {
|
||||
'IsDebuggerPresent', 'CheckRemoteDebuggerPresent', 'OutputDebugStringA', 'OutputDebugStringW',
|
||||
'GetTickCount', 'GetTickCount64', 'QueryPerformanceCounter', 'FindWindowA', 'FindWindowW',
|
||||
'EnumWindows', 'EnumChildWindows', 'GetWindowRect', 'GetClientRect', 'SetWindowDisplayAffinity',
|
||||
'UnhandledExceptionFilter', 'SetUnhandledExceptionFilter', 'IsProcessorFeaturePresent',
|
||||
'SetErrorMode', 'GetTimeZoneInformation', 'GetDriveTypeW', 'GetDiskFreeSpaceA'
|
||||
},
|
||||
'Keylogging': {
|
||||
'GetAsyncKeyState', 'GetKeyState', 'GetKeyboardState', 'MapVirtualKeyA', 'MapVirtualKeyW',
|
||||
'ToAscii', 'ToAsciiEx', 'ToUnicode', 'ToUnicodeEx', 'GetKeyNameTextA', 'GetForegroundWindow',
|
||||
'KeybdEvent', 'SendInput', 'MapVirtualKeyExA', 'MapVirtualKeyExW', 'CallNextHookEx'
|
||||
},
|
||||
'Input': {
|
||||
'GetCursorPos', 'SetCursorPos', 'MouseEvent', 'GetDoubleClickTime',
|
||||
'GetCapture', 'SetCapture'
|
||||
},
|
||||
'ScreenCapture': {
|
||||
'BitBlt', 'StretchBlt', 'GetDC', 'GetWindowDC', 'CreateCompatibleDC', 'CreateCompatibleBitmap',
|
||||
'GdipSaveImageToFile', 'PrintWindow', 'GetDesktopWindow', 'CreateDCW', 'CreateDCA',
|
||||
'SelectObject', 'DeleteDC', 'DeleteObject', 'GetDeviceCaps', 'GetSystemMetrics'
|
||||
},
|
||||
'Graphics': {
|
||||
'Direct3DCreate9', 'D3D11CreateDevice'
|
||||
},
|
||||
'Audio': {
|
||||
'WaveInOpen', 'WaveInClose', 'WaveInStart', 'WaveInStop'
|
||||
},
|
||||
'Clipboard': {
|
||||
'OpenClipboard', 'CloseClipboard', 'GetClipboardData', 'SetClipboardData'
|
||||
},
|
||||
'Camera': {
|
||||
'CapCreateCaptureWindowA', 'CapCreateCaptureWindowW'
|
||||
},
|
||||
'Memory': {
|
||||
'HeapAlloc', 'HeapFree', 'HeapSize', 'HeapCreate', 'GetProcessHeap',
|
||||
'LocalAlloc', 'LocalFree', 'GlobalAlloc', 'GlobalFree', 'GlobalUnlock',
|
||||
'HeapDestroy', 'GlobalLock', 'SysFreeString', 'SysAllocStringLen'
|
||||
},
|
||||
'Resource': {
|
||||
'LoadResource', 'SizeofResource', 'LockResource', 'FreeResource', 'FindResourceA'
|
||||
},
|
||||
'WindowControl': {
|
||||
'ShowWindow', 'DestroyWindow', 'TranslateMessage', 'DispatchMessageA', 'GetWindow',
|
||||
'PeekMessageA', 'GetWindowLongA', 'CallWindowProcA', 'SetWindowLongA', 'GetWindowTextA',
|
||||
'ScreenToClient', 'GetActiveWindow', 'CreateWindowExA', 'DefWindowProcA', 'GetMessageA',
|
||||
'RegisterClassA', 'UnregisterClassA', 'MessageBoxA'
|
||||
},
|
||||
'COM': {
|
||||
'CoCreateInstance', 'CoUninitialize', 'CoInitialize'
|
||||
}
|
||||
}
|
||||
|
||||
TARGET_DLLS = {
|
||||
'kernel32.dll', 'user32.dll', 'gdi32.dll', 'advapi32.dll', 'shell32.dll', 'ntdll.dll', 'hal.dll',
|
||||
'ws2_32.dll', 'wsock32.dll', 'wininet.dll', 'winhttp.dll', 'urlmon.dll', 'crypt32.dll', 'bcrypt.dll',
|
||||
'psapi.dll', 'dbghelp.dll', 'imagehlp.dll', 'shlwapi.dll', 'ole32.dll', 'oleaut32.dll', 'comctl32.dll',
|
||||
'mscoree.dll', 'vbscript.dll', 'netapi32.dll', 'iphlpapi.dll', 'wtsapi32.dll', 'version.dll', 'winmm.dll'
|
||||
}
|
||||
|
||||
BASE_SCHEMA = [
|
||||
"FileEntropy", "SectionMeanEntropy", "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",
|
||||
|
||||
"TextSectionMaxEntropy", "TextSectionMeanEntropy", "TextSizeRatio",
|
||||
"DataSectionMaxEntropy", "DataSectionMeanEntropy", "DataSizeRatio",
|
||||
"RsrcSectionMaxEntropy", "RsrcSectionMeanEntropy", "RsrcSizeRatio",
|
||||
"SectionCount", "ExecutableSections",
|
||||
"WritableSections", "ReadableSections", "SectionException",
|
||||
|
||||
"Char_00000020_Count", "Char_00000020_MeanEntropy",
|
||||
"Char_00000040_Count", "Char_00000040_MeanEntropy",
|
||||
"Char_00000080_Count", "Char_00000080_MeanEntropy",
|
||||
"Char_02000000_Count", "Char_02000000_MeanEntropy",
|
||||
"Char_20000000_Count", "Char_20000000_MeanEntropy",
|
||||
"Char_40000000_Count", "Char_40000000_MeanEntropy",
|
||||
"Char_80000000_Count", "Char_80000000_MeanEntropy",
|
||||
|
||||
"IconCount", "ApiCount", "ExportCount", "DebugCount", "ExceptionCount",
|
||||
"ImportCount", "ImportFunctionCount",
|
||||
|
||||
"FileDescriptionLength", "FileVersionLength", "ProductNameLength",
|
||||
"ProductVersionLength", "CompanyNameLength", "LegalCopyrightLength",
|
||||
"CommentsLength", "InternalNameLength", "LegalTrademarksLength",
|
||||
"SpecialBuildLength", "PrivateBuildLength",
|
||||
|
||||
"TrustSigned", "IsDebug", "IsPatched", "IsPrivateBuild", "IsPreRelease",
|
||||
"IsSpecialBuild", "IsAdmin", "IsInstall", "HasTlsCallbacks",
|
||||
"HasInvalidTimestamp", "HasRelocationDirectory", "HasPacked", "FileTimeException"
|
||||
]
|
||||
|
||||
CAT_SCHEMA = [f"Cat_{k}" for k in sorted(API_CAT_MAPPING.keys())]
|
||||
DLL_SCHEMA = [f"Dll_{d.replace('.', '_')}" for d in sorted(TARGET_DLLS)]
|
||||
|
||||
_ALL_APIS = {api for apis in API_CAT_MAPPING.values() for api in apis}
|
||||
API_SCHEMA = [f"Api_{api}" for api in sorted(_ALL_APIS)]
|
||||
|
||||
SCHEMA = BASE_SCHEMA + CAT_SCHEMA + DLL_SCHEMA + API_SCHEMA
|
||||
|
||||
_API_TO_CATS = {}
|
||||
for _cat, _apis in API_CAT_MAPPING.items():
|
||||
for _api in _apis:
|
||||
if _api not in _API_TO_CATS:
|
||||
_API_TO_CATS[_api] = []
|
||||
_API_TO_CATS[_api].append(_cat)
|
||||
|
||||
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 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 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 float(n) / d if d > 0 else 0.0
|
||||
|
||||
def process_single_file_content(file_bytes, file_path):
|
||||
fsize = len(file_bytes)
|
||||
if fsize == 0: return None
|
||||
|
||||
fts = {k: 0.0 for k in Features.SCHEMA}
|
||||
pe = None
|
||||
try:
|
||||
pe = pefile.PE(data=file_bytes, 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.0 if (fh.TimeDateStamp < 631152000 or fh.TimeDateStamp > curr_ts + 2592000) else 0.0
|
||||
fts['FileTimeException'] = 1.0 if fh.TimeDateStamp == 0 else 0.0
|
||||
|
||||
if hasattr(pe, 'OPTIONAL_HEADER'):
|
||||
op = pe.OPTIONAL_HEADER
|
||||
fts['Magic'] = getattr(op, 'Magic', 0)
|
||||
fts['MajorLinkerVersion'] = getattr(op, 'MajorLinkerVersion', 0)
|
||||
fts['MinorLinkerVersion'] = getattr(op, 'MinorLinkerVersion', 0)
|
||||
fts['SizeOfCode'] = getattr(op, 'SizeOfCode', 0)
|
||||
fts['SizeOfInitializedData'] = getattr(op, 'SizeOfInitializedData', 0)
|
||||
fts['SizeOfUninitializedData'] = getattr(op, 'SizeOfUninitializedData', 0)
|
||||
fts['AddressOfEntryPoint'] = getattr(op, 'AddressOfEntryPoint', 0)
|
||||
fts['BaseOfCode'] = getattr(op, 'BaseOfCode', 0)
|
||||
fts['ImageBase'] = getattr(op, 'ImageBase', 0)
|
||||
fts['SectionAlignment'] = getattr(op, 'SectionAlignment', 0)
|
||||
fts['FileAlignment'] = getattr(op, 'FileAlignment', 0)
|
||||
fts['MajorOperatingSystemVersion'] = getattr(op, 'MajorOperatingSystemVersion', 0)
|
||||
fts['MinorOperatingSystemVersion'] = getattr(op, 'MinorOperatingSystemVersion', 0)
|
||||
fts['MajorImageVersion'] = getattr(op, 'MajorImageVersion', 0)
|
||||
fts['MinorImageVersion'] = getattr(op, 'MinorImageVersion', 0)
|
||||
fts['MajorSubsystemVersion'] = getattr(op, 'MajorSubsystemVersion', 0)
|
||||
fts['MinorSubsystemVersion'] = getattr(op, 'MinorSubsystemVersion', 0)
|
||||
fts['SizeOfImage'] = getattr(op, 'SizeOfImage', 0)
|
||||
fts['SizeOfHeaders'] = getattr(op, 'SizeOfHeaders', 0)
|
||||
fts['CheckSum'] = getattr(op, 'CheckSum', 0)
|
||||
fts['Subsystem'] = getattr(op, 'Subsystem', 0)
|
||||
fts['DllCharacteristics'] = getattr(op, 'DllCharacteristics', 0)
|
||||
fts['SizeOfStackReserve'] = getattr(op, 'SizeOfStackReserve', 0)
|
||||
fts['SizeOfStackCommit'] = getattr(op, 'SizeOfStackCommit', 0)
|
||||
fts['SizeOfHeapReserve'] = getattr(op, 'SizeOfHeapReserve', 0)
|
||||
fts['SizeOfHeapCommit'] = getattr(op, 'SizeOfHeapCommit', 0)
|
||||
fts['LoaderFlags'] = getattr(op, 'LoaderFlags', 0)
|
||||
fts['NumberOfRvaAndSizes'] = getattr(op, 'NumberOfRvaAndSizes', 0)
|
||||
fts['Is64Bit'] = 1.0 if fh.Machine in (0x8664, 0xAA64, 0x0200) else 0.0
|
||||
fts['IsExe'] = 1.0 if pe.is_exe() else 0.0
|
||||
fts['IsDll'] = 1.0 if pe.is_dll() else 0.0
|
||||
fts['IsDriver'] = 1.0 if fts['Subsystem'] == 1 else 0.0
|
||||
|
||||
if hasattr(op, 'DATA_DIRECTORY'):
|
||||
reloc_idx = pefile.DIRECTORY_ENTRY.get('IMAGE_DIRECTORY_ENTRY_BASERELOC', 5)
|
||||
if len(op.DATA_DIRECTORY) > reloc_idx and op.DATA_DIRECTORY[reloc_idx].Size > 0:
|
||||
fts['HasRelocationDirectory'] = 1.0
|
||||
|
||||
try:
|
||||
fts['FileEntropy'] = calc_entropy(file_bytes)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
sec_entropies = []
|
||||
text_entropies = []
|
||||
data_entropies = []
|
||||
rsrc_entropies = []
|
||||
char_flags = [0x00000020, 0x00000040, 0x00000080, 0x02000000, 0x20000000, 0x40000000, 0x80000000]
|
||||
|
||||
if hasattr(pe, 'sections'):
|
||||
fts['SectionCount'] = len(pe.sections)
|
||||
for section in pe.sections:
|
||||
try:
|
||||
name = section.Name.decode('ascii', 'ignore').strip('\x00')
|
||||
except Exception:
|
||||
name = ""
|
||||
|
||||
try:
|
||||
s_data = section.get_data()
|
||||
s_entropy = calc_entropy(s_data)
|
||||
except Exception:
|
||||
s_data = b""
|
||||
s_entropy = 0.0
|
||||
|
||||
sec_entropies.append(s_entropy)
|
||||
|
||||
if any(p in name.lower() for p in Features.PACKERS): fts['HasPacked'] = 1.0
|
||||
if section.Characteristics & 0x20000000: fts['ExecutableSections'] += 1.0
|
||||
if section.Characteristics & 0x80000000: fts['WritableSections'] += 1.0
|
||||
if section.Characteristics & 0x40000000: fts['ReadableSections'] += 1.0
|
||||
if section.SizeOfRawData + section.PointerToRawData > fsize: fts['SectionException'] = 1.0
|
||||
|
||||
for flag in char_flags:
|
||||
if section.Characteristics & flag:
|
||||
fts[f'Char_{flag:08X}_Count'] += 1.0
|
||||
fts[f'Char_{flag:08X}_MeanEntropy'] += s_entropy
|
||||
|
||||
ratio = safe_div(section.SizeOfRawData, fsize)
|
||||
if name.startswith('.text'):
|
||||
text_entropies.append(s_entropy)
|
||||
fts['TextSizeRatio'] += ratio
|
||||
elif name.startswith('.data'):
|
||||
data_entropies.append(s_entropy)
|
||||
fts['DataSizeRatio'] += ratio
|
||||
elif name.startswith('.rsrc'):
|
||||
rsrc_entropies.append(s_entropy)
|
||||
fts['RsrcSizeRatio'] += ratio
|
||||
if b"requireAdministrator" in s_data: fts['IsAdmin'] = 1.0
|
||||
for sig in Features.INSTALLER_SIGS:
|
||||
if sig in s_data:
|
||||
fts['IsInstall'] = 1.0
|
||||
break
|
||||
|
||||
fts['SectionMeanEntropy'] = safe_div(sum(sec_entropies), len(sec_entropies))
|
||||
fts['TextSectionMaxEntropy'] = max(text_entropies) if text_entropies else 0.0
|
||||
fts['TextSectionMeanEntropy'] = safe_div(sum(text_entropies), len(text_entropies))
|
||||
fts['DataSectionMaxEntropy'] = max(data_entropies) if data_entropies else 0.0
|
||||
fts['DataSectionMeanEntropy'] = safe_div(sum(data_entropies), len(data_entropies))
|
||||
fts['RsrcSectionMaxEntropy'] = max(rsrc_entropies) if rsrc_entropies else 0.0
|
||||
fts['RsrcSectionMeanEntropy'] = safe_div(sum(rsrc_entropies), len(rsrc_entropies))
|
||||
|
||||
for flag in char_flags:
|
||||
fts[f'Char_{flag:08X}_MeanEntropy'] = safe_div(fts[f'Char_{flag:08X}_MeanEntropy'], fts[f'Char_{flag:08X}_Count'])
|
||||
|
||||
try:
|
||||
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'],
|
||||
pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_TLS']
|
||||
])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if hasattr(pe, 'DIRECTORY_ENTRY_TLS') and hasattr(pe.DIRECTORY_ENTRY_TLS, 'struct'):
|
||||
if getattr(pe.DIRECTORY_ENTRY_TLS.struct, 'AddressOfCallBacks', 0) != 0:
|
||||
fts['HasTlsCallbacks'] = 1.0
|
||||
|
||||
if hasattr(pe, 'VS_FIXEDFILEINFO') and len(pe.VS_FIXEDFILEINFO) > 0:
|
||||
flags = getattr(pe.VS_FIXEDFILEINFO[0], 'FileFlags', 0)
|
||||
fts['IsDebug'] = 1.0 if flags & 0x1 else 0.0
|
||||
fts['IsPreRelease'] = 1.0 if flags & 0x2 else 0.0
|
||||
fts['IsPatched'] = 1.0 if flags & 0x4 else 0.0
|
||||
fts['IsPrivateBuild'] = 1.0 if flags & 0x8 else 0.0
|
||||
fts['IsSpecialBuild'] = 1.0 if flags & 0x20 else 0.0
|
||||
|
||||
if hasattr(pe, 'FileInfo'):
|
||||
for fileinfo_list in pe.FileInfo:
|
||||
for fileinfo in fileinfo_list:
|
||||
if getattr(fileinfo, 'name', '') in ('StringFileInfo', b'StringFileInfo'):
|
||||
for st in getattr(fileinfo, 'StringTable', []):
|
||||
for key, val in st.entries.items():
|
||||
try:
|
||||
k = key.decode('utf-8', 'ignore') if isinstance(key, bytes) else str(key)
|
||||
v = val.decode('utf-8', 'ignore') if isinstance(val, bytes) else str(val)
|
||||
length = len(v)
|
||||
if k == 'FileDescription': fts['FileDescriptionLength'] = length
|
||||
elif k == 'FileVersion': fts['FileVersionLength'] = length
|
||||
elif k == 'ProductName': fts['ProductNameLength'] = length
|
||||
elif k == 'ProductVersion': fts['ProductVersionLength'] = length
|
||||
elif k == 'CompanyName': fts['CompanyNameLength'] = length
|
||||
elif k == 'LegalCopyright': fts['LegalCopyrightLength'] = length
|
||||
elif k == 'Comments': fts['CommentsLength'] = length
|
||||
elif k == 'InternalName': fts['InternalNameLength'] = length
|
||||
elif k == 'LegalTrademarks': fts['LegalTrademarksLength'] = length
|
||||
elif k == 'SpecialBuild': fts['SpecialBuildLength'] = length
|
||||
elif k == 'PrivateBuild': fts['PrivateBuildLength'] = length
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
|
||||
fts['ImportCount'] = len(pe.DIRECTORY_ENTRY_IMPORT)
|
||||
for entry in pe.DIRECTORY_ENTRY_IMPORT:
|
||||
if getattr(entry, 'dll', None):
|
||||
try:
|
||||
dll_name = entry.dll.decode('ascii', 'ignore').lower()
|
||||
if dll_name in Features.TARGET_DLLS:
|
||||
fts[f"Dll_{dll_name.replace('.', '_')}"] = 1.0
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
imports = getattr(entry, 'imports', [])
|
||||
for imp in imports:
|
||||
fts['ImportFunctionCount'] += 1.0
|
||||
if not getattr(imp, 'name', None): continue
|
||||
try:
|
||||
func_name = imp.name.decode('ascii', 'ignore')
|
||||
if func_name in Features._ALL_APIS:
|
||||
fts[f'Api_{func_name}'] += 1.0
|
||||
fts['ApiCount'] += 1.0
|
||||
for cat in Features._API_TO_CATS.get(func_name, []):
|
||||
fts[f'Cat_{cat}'] += 1.0
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT') and hasattr(pe.DIRECTORY_ENTRY_EXPORT, 'symbols'):
|
||||
fts['ExportCount'] = len(pe.DIRECTORY_ENTRY_EXPORT.symbols)
|
||||
|
||||
if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
|
||||
for entry in pe.DIRECTORY_ENTRY_RESOURCE.entries:
|
||||
if getattr(entry, 'id', None) == 3 and hasattr(entry, 'directory'):
|
||||
fts['IconCount'] += len(getattr(entry.directory, 'entries', []))
|
||||
|
||||
if hasattr(pe, 'OPTIONAL_HEADER') and hasattr(pe.OPTIONAL_HEADER, 'DATA_DIRECTORY') and len(pe.OPTIONAL_HEADER.DATA_DIRECTORY) > 3:
|
||||
exc_dir = pe.OPTIONAL_HEADER.DATA_DIRECTORY[3]
|
||||
if exc_dir.Size > 0:
|
||||
fts['ExceptionCount'] = exc_dir.Size // 12 if fts['Machine'] in (0x8664, 0xAA64) else 0.0
|
||||
|
||||
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 pefile.PEFormatError:
|
||||
return None
|
||||
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 = "FileHash TEXT, " + ", ".join([f"{c} REAL" for c in Features.SCHEMA])
|
||||
conn.execute(f"CREATE TABLE IF NOT EXISTS PeData ({cols}, Label INTEGER)")
|
||||
conn.execute(f"CREATE UNIQUE INDEX IF NOT EXISTS idx_pedata_hash ON PeData (FileHash)")
|
||||
conn.commit()
|
||||
return conn
|
||||
|
||||
def load_existing_hashes(conn):
|
||||
print("[*] Loading existing hashes into memory...")
|
||||
try:
|
||||
cursor = conn.execute("SELECT FileHash FROM PeData")
|
||||
return {row[0] for row in cursor.fetchall()}
|
||||
except:
|
||||
return set()
|
||||
|
||||
####################################################################################################
|
||||
|
||||
def scan_and_save(conn, path, label, existing_hashes):
|
||||
print(f"\n[*] Scanning: {path} (Label={label})")
|
||||
print(f"[*] Config: Max File Size = {MAX_FILE_SIZE/1024/1024:.0f} MB")
|
||||
|
||||
files = []
|
||||
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.")
|
||||
return
|
||||
|
||||
print(f"[*] Found {total} files. Processing...\n")
|
||||
|
||||
batch = []
|
||||
count = 0
|
||||
errors = 0
|
||||
skipped = 0
|
||||
start_time = time.time()
|
||||
|
||||
placeholders = ",".join(["?"] * (len(Features.SCHEMA) + 2))
|
||||
sql = f"INSERT INTO PeData VALUES ({placeholders})"
|
||||
|
||||
try:
|
||||
for i, file_path in enumerate(files):
|
||||
try:
|
||||
fsize = os.path.getsize(file_path)
|
||||
if fsize == 0 or fsize > MAX_FILE_SIZE:
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
with open(file_path, "rb") as f:
|
||||
file_bytes = f.read()
|
||||
|
||||
sha256 = hashlib.sha256(file_bytes).hexdigest()
|
||||
if sha256 in existing_hashes:
|
||||
skipped += 1
|
||||
else:
|
||||
res = process_single_file_content(file_bytes, file_path)
|
||||
|
||||
if res:
|
||||
vals = [sha256]
|
||||
vals.extend([res.get(c, 0.0) for c in Features.SCHEMA])
|
||||
vals.append(float(label))
|
||||
batch.append(tuple(vals))
|
||||
|
||||
existing_hashes.add(sha256)
|
||||
count += 1
|
||||
else:
|
||||
errors += 1
|
||||
|
||||
except Exception:
|
||||
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}")
|
||||
batch = []
|
||||
|
||||
elapsed = time.time() - start_time
|
||||
rate = (i + 1) / elapsed if elapsed > 0 else 0
|
||||
sys.stdout.write(f"\r[{i+1}/{total}] New: {count} | Skip: {skipped} | 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:
|
||||
try:
|
||||
conn.executemany(sql, batch)
|
||||
conn.commit()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
print(f"\n\n[+] Scan finished. Total New: {count}, Total Skipped: {skipped}")
|
||||
|
||||
####################################################################################################
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("\n---------------- PE Dataset Builder v3.2 ----------------\n")
|
||||
|
||||
if os.path.exists(DB_PATH):
|
||||
try:
|
||||
conn_check = sqlite3.connect(DB_PATH)
|
||||
cursor = conn_check.execute("PRAGMA table_info(PeData)")
|
||||
cols = [row[1] for row in cursor.fetchall()]
|
||||
if 'FileHash' not in cols or len(cols) != len(Features.SCHEMA) + 2:
|
||||
print(f"[-] WARNING: DB Schema mismatch. Please delete {DB_PATH} to rebuild.")
|
||||
conn_check.close()
|
||||
except: pass
|
||||
|
||||
conn = init_db()
|
||||
|
||||
existing_hashes = load_existing_hashes(conn)
|
||||
print(f"[+] Loaded {len(existing_hashes)} hashes from database.\n")
|
||||
|
||||
try:
|
||||
while True:
|
||||
print("-" * 60)
|
||||
raw_path = input("\n[*] 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.")
|
||||
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
|
||||
print("[-] Please enter 0 or 1.")
|
||||
|
||||
scan_and_save(conn, target_path, label, existing_hashes)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n[-] Interrupted.")
|
||||
finally:
|
||||
conn.close()
|
||||
print(f"\n[+] Database saved to: {os.path.abspath(DB_PATH)}")
|
||||
@@ -0,0 +1,217 @@
|
||||
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 = "model.txt"
|
||||
ONNX_FILE = "model.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': 31,
|
||||
'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': 10,
|
||||
'lambda_l1': 0.1,
|
||||
'lambda_l2': 0.1,
|
||||
}
|
||||
|
||||
####################################################################################################
|
||||
|
||||
def clean_col_name(name):
|
||||
return re.sub(r'[^A-Za-z0-9_]+', '', name)
|
||||
|
||||
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 = {'label', 'id', 'filename', 'filelength', 'rowid', 'probability', 'predictedlabel', 'score', 'filehash', 'timedatestamp'}
|
||||
return [c for c in columns if c.lower().strip() not in exclude]
|
||||
except Exception as e:
|
||||
print(f"[-] Schema extraction error: {e}")
|
||||
return None
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
####################################################################################################
|
||||
|
||||
def load_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:
|
||||
chunks = []
|
||||
for chunk in pd.read_sql_query(sql, conn, chunksize=20000):
|
||||
label_col = next((c for c in chunk.columns if c.lower().strip() == 'label'), None)
|
||||
if not label_col:
|
||||
print("[-] Critical Error: Label column not found.")
|
||||
return None, None, None
|
||||
|
||||
cols_to_cast = [c for c in chunk.columns if c != label_col]
|
||||
chunk[cols_to_cast] = chunk[cols_to_cast].astype(np.float32)
|
||||
chunk[label_col] = chunk[label_col].astype(np.int8)
|
||||
chunks.append(chunk)
|
||||
|
||||
if not chunks:
|
||||
return None, None, None
|
||||
|
||||
df = pd.concat(chunks, ignore_index=True)
|
||||
|
||||
label_col = next((c for c in df.columns if c.lower().strip() == 'label'), 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()
|
||||
|
||||
rename_map = {old: clean_col_name(old) for old in X.columns}
|
||||
X = X.rename(columns=rename_map)
|
||||
|
||||
if X.columns.duplicated().any():
|
||||
print("[-] Warning: Duplicate column names detected after cleaning. Deduplicating...")
|
||||
X = X.loc[:, ~X.columns.duplicated()]
|
||||
|
||||
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_target = 0.01
|
||||
final_pos_weight = base_weight * weight_ratio_target
|
||||
|
||||
print(f"[*] Balance Report: Safe={n_neg}, Malware={n_pos}")
|
||||
print(f"[*] Weight Config: Base Balanced={base_weight:.4f}, Final Adjusted={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...")
|
||||
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.1 ----------------\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_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}")
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,15 +0,0 @@
|
||||
ExcludeXMD =
|
||||
Extensions = exe;com;dll;ocx;scr;bin;dat;386;vxd;sys;wdm;cla;class;ovl;ole;hlp;doc;dot;xls;ppt;wbk;wiz;pot;ppa;xla;xlt;vbs;vbe;mdb;rtf;htm;hta;html;xml;xtp;php;asp;js;shs;chm;lnk;pif;prc;url;smm;pfd;msi;ini;csc;cmd;bas;nws;
|
||||
ExcludeExtensions =
|
||||
ConfigFile = bdc.ini
|
||||
HttpProxy =
|
||||
InfectedFolder = Infected
|
||||
SuspectedFolder = Suspected
|
||||
LogMaxSize = 1024
|
||||
RenameExtension = vir
|
||||
PluginsPaths = Plugins
|
||||
LogName = bdc.log
|
||||
UpdateHttpLocation = http://upgrade.bitdefender.com/av32bit-eps
|
||||
XMD = *
|
||||
LastUpdate = Wed Feb 18 16:39:59 2009
|
||||
ProductID = {AAD1516D-28AB-4EB5-B7C8-DF54FE4442E9}
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
<p>AVCORE v2.2 Windows/i386 11.0.1.21 (August 15, 2021)</p>
|
||||
<p>disp.xmd - Dispatcher (0.00) 0x1[997] (r)</p>
|
||||
<p>pyinstaller.xmd - PYInstaller unpacker (1.0) 0x8[12] (r)</p>
|
||||
<p>rar.xmd - RAR5 unpacker (0.5) 0xA[12] (r)</p>
|
||||
<p>thebat.xmd - TheBat Engine (0.03a) 0x4010[12] (r) +</p>
|
||||
<p>html.xmd - HTML Parser (1.0) 0x4008[11] (r) +</p>
|
||||
<p>mdx.xmd - Macro Defense Expert (3.57b) 0x1[11] 1[0] (r)</p>
|
||||
<p>cevakrnl.xmd - CEVA (0.03a) 0x1[10] (r)</p>
|
||||
<p>pdf.xmd - PDF Engine (2.0) 0x4009[10] (r) +</p>
|
||||
<p>imp.xmd - IMP (1.4.2) 0x2[9] (r)</p>
|
||||
<p>sfx.xmd - Sfx Engine (1.8.6) 0xA[9] (r)</p>
|
||||
<p>sdx.xmd - SDX () 0x1[5] 191729[0] (r)</p>
|
||||
<p>jpeg.xmd - JPEG Engine (0.05) 0x1[1] 14[1] (r)</p>
|
||||
<p>rtf.xmd - RTF (1.0) 0x4008[0] (r) +</p>
|
||||
Binary file not shown.
-21
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020-2024 87owo (PYAS Security)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
87owo Publicly Available Source Code License Agreement
|
||||
Last updated: 2025-12-19
|
||||
|
||||
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 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. 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 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 and Liability
|
||||
- All services and assets are provided "as is" without any form of warranty.
|
||||
- 87owo is not liable for any direct or indirect damages from software use.
|
||||
- Users assume all risks regarding performance, data, and system integrity.
|
||||
|
||||
© 2020-2026 87owo (PYAS Security). All rights reserved.
|
||||
@@ -1 +0,0 @@
|
||||
{"Unknown": [38413146381396798812836662586219087594480760119241756145287379993031670453973, 96759775057307603829199050115151442660431386536877578909394799687553144825391], "White": [92860071170291586757870565976957954052649178883790647665503983139114277816413, 50625869624179221836524636484722091669820057030729734765256925026245308185143, 79303266820014134748061006437377483029320717142203104125806969476209010566146, 50391760446499089493384482654016917630509060287507523223191455177998253781572, 34733894651460458125941968926483828168477919119649839915356573816494375383659, 16447578251589668808184123721615810667991570306415913809506896532563163557975, 18668853151306203943053249777678854424409647574074706653144503993068509738028, 16447129799599854768187525514242197965987640167415805965954293039200573272151, 42965648781535883376480003940402366467478625051031283341289116138472520399484, 45637511530246203537935382208327538642024163565740899790237852717178844340385, 100662025713257198141308144602569453810226448934776598411982222249289646045820, 2813878798545665948450767843887867208740292941021073849284371582085785669685, 54695748401254225125045716155327877471149349614359435230254611073117412307518, 27428665293760567560050957450577436769403462770366418052177943137905489504373, 32018095881556959863902669246154132691484124511748151111295836576906027842532, 82735669648112373508385530969898006750362429118827185652448450648454052106395, 27853809242729492000984914092533936796891917926358854729439436487683423285261, 20030429995379197455160031864140436552884002299333955332088108013764717533796, 82338140557728967648601024370995428985866052631101882076231147335348455671038, 71339449324799277130427957011381342555145697382104653874846579353871764366968, 2432232479351500614611699169184443988440809841079862157291791071419485606436, 9463527399566410848087352636323112952591923803840644609432039785310381355253, 17287926889345790925003722717807755244540044472850272987265624141065166747251, 31507509644511868166890345905396462199402122513677304280568315890707028374136, 92802443753971611323223428952970105040389824130209263287070763891097867755624, 60491018752293550079699763462944244393253888103551546202593483014975813742967, 45133408084728538869955951560598604064861024543940290379768365214821771604584, 6759146298068049614085390992799666053918974602489525613718797088468975708017, 43161770374046173333870752071317153674965637163816017117315179871715332666383, 55200886519442939000007636174371797768786544863806926514781108850256791225983, 102124766481586899841647737641698083212305154684644839980199278690335383712492, 52992286898317605666180786036367620316269750824654214415314225077986227890804, 96307454545313440124283308270263825589093792315386382296096934270155352236733, 36073459579994433898643313577597321150634749356791285363958792075031385371364, 5354562433688861244299028006341553420425390015040147574513776499404802540118, 2671602537216404752611755689384448521170725107261295121211275163689399347529, 31174448189678483951801405655647041557287598300853213718404097030076935043252, 817984956081990458969224676381868506770627801582748844000835755782736667191, 6997953573828232905847825866256444005094471443450029313008738013465446666864, 41288968033780608769032189481784193916730262129846893330891418484950645535282, 56724589038911745751056508177185337741291265472470897077742981563488398484126, 3353938097938067320481103667469354721822387389147415219233498938990215839034, 21195721951654457114265478558602466514207347021822959737607658828495062116920, 2916561284514958799877078174216081002558870786437593202464334407456915288119, 93137488384582768487662730765406914258099784103320160609442537879778117334700, 21195721951654457114265478558602377311225888285332501136798116331518898022972, 85036278951571446667616241901438186945472743486751871120301019617002115253240, 14623491695050192413097067629676318500123044497134202517578785087180871258165, 2022308710750553104057453378681448926020203033444470910346149752954363011822, 16435447118324352510213480738895714506136417806014749563314727656196027207884, 20110908101408861236178371339075650317185505287106087252378028881915405550816, 97262306467112548995108413358594977802790545321935863056096364390382492643957, 96614497885586867524036482497010189662872359368622249290846422070379022959337, 1895288773648887609359329471072769468085207279473521707976899919066265183340, 2651591106060448314208209841614702280337184080195391257416359882876000875095, 114619913163036058498985801603082782363327281628924544162718017899237779173997, 2481883953883130814217575190747389944608730963897863224598923997640828351014, 45000300637061336566799421885334051647634671537987073940268834014403441552901, 79047998258892679051555952202178856054614923426747250310189496005785954516966, 92887093185298651693450115442544102614083847612212241647641096093293220418098, 7140769773119319253009453104401896171570019200295580355390762162793695491644, 17012496707Line truncated
|
||||
+555
@@ -0,0 +1,555 @@
|
||||
translate_dict = {
|
||||
"traditional_switch": {"开启":"開啟","关闭":"關閉","On":"開啟","Off":"關閉"},
|
||||
|
||||
"simplified_switch": {"開啟":"开启","關閉":"关闭","On":"开启","Off":"关闭",
|
||||
"錯誤":"错误","發現":"发现","關閉":"关闭","裝置":"设备","記憶體":"内存",
|
||||
"軟體":"软件","檔案":"文件","確定":"确认","設定":"设置","關於":"关于",
|
||||
"總數":"总数","註冊":"注册","圖標":"图标","路徑":"路径","網路":"网络",
|
||||
"位元":"字节","靈敏":"敏感","複製":"复制","開啟":"开启","靜態":"静态",
|
||||
"訊":"讯","項":"项","掃":"扫","試":"试","黃":"黄","嗎":"吗","防":"保",
|
||||
"鑰":"钥","當":"当","後":"后","護":"护","導":"导","區":"区","復":"复",
|
||||
"攔":"拦","請":"请","統":"统","刪":"删","進":"进","個":"个","選":"选",
|
||||
"啟":"启","監":"监","並":"并","徑":"径","盤":"盘","隱":"隐","動":"动",
|
||||
"狀":"状","誌":"志","這":"这","會":"会","題":"题","擇":"择","語":"语",
|
||||
"無":"无","顯":"显","變":"变","戶":"户","碼":"码","雲":"云","介":"界",
|
||||
"稱":"称","類":"类","輸":"输","執":"执","數":"数","尋":"寻","網":"网",
|
||||
"詢":"询","製":"制","員":"员","許":"许","條":"条","藍":"蓝","紅":"红",
|
||||
"綠":"绿","態":"态","務":"务","連":"连","檢":"检","測":"测","關":"关",
|
||||
"強":"强","驅":"驱","為":"为","腳":"脚","單":"单","開":"开","擴":"扩",
|
||||
"惡":"恶","據":"据","庫":"库","經":"经","敗":"败","謝":"谢","別":"别",
|
||||
"載":"载","誤":"误","報":"报","鏈":"链","竄":"窜","蹤":"踪","與":"与",
|
||||
"異":"异","實":"实","時":"时","彈":"弹","窗":"窗","暫":"暂","訂":"订",
|
||||
"資":"资","產":"产","金":"密","離":"离","規":"规","則":"则","來":"来",
|
||||
"殼":"壳","碼":"码","線":"线","餘":"余",},
|
||||
|
||||
"english_switch": {"開啟":"On","關閉":"Off","开启":"On","关闭":"Off",",":", ",
|
||||
"立即刪除":"Delete Now","安全模式":"Safe Mode","官方網站":"Official Website ",
|
||||
"腳本":"Script ","鏈式":"Chain ","記憶體":"Memory ","正在加載":"Loading ","加載":"Load ",
|
||||
"行為":"Behavior ","可疑":"Suspicious ","勒索":"Ransom ","主要":"Main ",
|
||||
"許可條款":"License Terms ","惡意":"Malicious", "開發":"Developers ",
|
||||
"啟用":"Enable ","禁用":"Disable ","正在初始化中":"Initializing ","初始化":"initialize ",
|
||||
"正在掃描":"Scanning ","正在刪除":"Deleting ","正在追蹤":"Tracking ",
|
||||
"最小化到":"Minimize To ","靈敏度":"Sensitivity ","正在檢查":"Checking ",
|
||||
"確定要":"Sure Want To ","引擎靈敏度":"Sensitivity ","更新":"Update ",
|
||||
"白色主題":"White","黃色主題":"Yellow","紅色主題":"Red","語言":"Language ",
|
||||
"藍色主題":"Blue","綠色主題":"Green","自訂主題":"Custom","黑色主題":"Black",
|
||||
"特別感謝":"Contributors ","版本資訊":"Information","通訊":"Connect ",
|
||||
"註冊":"Registry ","退出":"Quit ","檔案":"File ","當前":"Currently ",
|
||||
"狀態":"State ","掃描":"Scan ","工具":"Tools ","防護":"Protect ",
|
||||
"失敗":"Failed ","請":"Please ","路徑":"Path ","方式":"Method ",
|
||||
"需要":"Need ","病毒":"Virus ","選擇":"Select ","返回":"Back",
|
||||
"受到":"Been ","錯誤":"Error","完成":"Complete ","引擎":"Engine ",
|
||||
"托盤":"Tray ","圖標":"Icon ","不安全":"Unsafe","增強":"Enhance ",
|
||||
"系統":"System ","雲端":"Cloud ","重啟":"Reboot ","修復":"Repair ",
|
||||
"裝置":"Device ","發現":"Found ","成功":"Success ","清理":"Cleanup ",
|
||||
"確定":"OK","執行":"Execute ","警告":"Warning ","使用":"Use ",
|
||||
"網路":"Network ","變更":"Change ","總數":"Total","結束":"End ",
|
||||
"選項":"Options ","監控":"Monitor ","連接":"Connect ","可以":"Can ",
|
||||
"進程":"Process ","攔截":"Block ","引導":"Boot ","刪除":"Delete ",
|
||||
"分區":"Partition ","設定":"Setting ","關於":"About","模式":"Mode ",
|
||||
"提高":"Improve ","安全":"Security ","顯色":"Color ","顏色":"Color ",
|
||||
"主題":"Theme ", "回收":"Collect ", "無用":"Useless ","導入":"Import ",
|
||||
"風險":"Risk ","介面":"UI ","核心":"Core ","服務":"Services ",
|
||||
"管理":"Manage","所有":"All ","您":"You ","取消":"Cancel ","未":"Not ",
|
||||
"垃圾":"Junk ","位元":"byte ","本機":"Computer ","停止":"Stop ",
|
||||
"到":"To ","白名單":"White List ","軟體":"Software ","正在":"",
|
||||
"增加":"Add ","移除":"Delete ","項目":"Items ","生成":"Create ","稱":"",
|
||||
"複製":"Copy ","此":"This ","並":"And ","全盤":"Full ","最新":"Latest ",
|
||||
"已存在":"Already ","數據庫":"Database ","誤報":"False Positive ",
|
||||
"高":"High ","新":"New ","和":"And ","可能會":"Possible ","會":"Can ",
|
||||
"日誌":"Log","已":"Has ","彈窗":"Window ","要":"To ","驅動":"Driver ",
|
||||
"的":"","顯示":"","個":"","嗎":"","了":"","行":"","立即":"","規則":"Rule ",
|
||||
"密鑰":"Key ","檢測":"Detect ","製作":"Maker ","運行":"Running",
|
||||
"擴展":"Extension ","套件":"Kit ","自動":"Auto ","上報":"Report ",
|
||||
"分析":"Analysis ","自身":"Self ","其他":"Other ","配置":"Config ",
|
||||
"丟失":"Lost ","網站":"Website ","不兼容":"Not Compatible ","列表":"List ",
|
||||
"竄改":"Tamper ","第三方":"Other ","實時":"Real Time ","查看":"View ",
|
||||
"指定":"Specify ","清空":"Empty ","資源回收桶":"Recycle Bin ", "無法":"Cannot ",
|
||||
"與":"With ","當":"When ","功能":"Function ","異常":"Abnormal ", "來":"To ",
|
||||
"重置":"Reset ","窗口":"Window ","暫存":"Temp ","自訂":"Custom ",
|
||||
"不支持":"Not Support ","共":"Total ","秒":"Seconds ","耗時":"Takes ",
|
||||
"沙箱":"Sandbox ", "虛擬":"Virtual ", "隔離":"Quarantine ", "時":"",
|
||||
"建立":"Create ","環境":"Environment ","化":"","表":"",
|
||||
"達":"Reached ", "上限":"Limit ", "區":"", "金鑰":"Key ", "產品":"Product ",
|
||||
"運行庫":".NET CLR ","殼碼":"Shellcode ","線程":"Thread ","注入":"Inject ",
|
||||
"前往":"Go ","檢查":"Check ","可用":"Available ","靜態":"Static ",
|
||||
"版本":"Version ","是":"","剩餘":"Remain ","遠控":"Remote "," ":" "},
|
||||
|
||||
"japanese_switch": {"開啟":"オン","關閉":"オフ","开启":"オン","关闭":"オフ",",":", ",
|
||||
"立即刪除":"即時削除","安全模式":"セーフモード","官方網站":"公式サイト",
|
||||
"腳本":"スクリプト","鏈式":"チェーン","記憶體":"メモリ","正在加載":"読み込み中","加載":"ロード",
|
||||
"行為":"振る舞い","可疑":"疑わしい","勒索":"ランサム","主要":"メイン",
|
||||
"許可條款":"ライセンス条項","惡意":"悪意のある","開發":"開発",
|
||||
"啟用":"有効化","禁用":"無効化","正在初始化中":"初期化中","初始化":"初期化",
|
||||
"正在掃描":"スキャン中","正在刪除":"削除中","正在追蹤":"追跡中",
|
||||
"最小化到":"最小化先","靈敏度":"感度","正在檢查":"確認中",
|
||||
"確定要":"本当によろしいですか","引擎靈敏度":"エンジン感度","更新":"更新",
|
||||
"白色主題":"ホワイト","黃色主題":"イエロー","紅色主題":"レッド","語言":"言語",
|
||||
"藍色主題":"ブルー","綠色主題":"グリーン","自訂主題":"カスタム","黑色主題":"ブラック",
|
||||
"特別感謝":"貢献者","版本資訊":"バージョン情報","通訊":"通信",
|
||||
"註冊":"レジストリ","退出":"終了","檔案":"ファイル","當前":"現在の",
|
||||
"狀態":"状態","掃描":"スキャン","工具":"ツール","防護":"保護",
|
||||
"失敗":"失敗","請":"してください","路徑":"パス","方式":"方式",
|
||||
"需要":"必要","病毒":"ウイルス","選擇":"選択","返回":"戻る",
|
||||
"受到":"受けた","錯誤":"エラー","完成":"完了","引擎":"エンジン",
|
||||
"托盤":"トレイ","圖標":"アイコン","不安全":"非セキュア","增強":"強化",
|
||||
"系統":"システム","雲端":"クラウド","重啟":"再起動","修復":"修復",
|
||||
"裝置":"デバイス","發現":"検出","成功":"成功","清理":"クリーンアップ",
|
||||
"確定":"確定","執行":"実行","警告":"警告","使用":"使用",
|
||||
"網路":"ネットワーク","變更":"変更","總數":"合計","結束":"終了",
|
||||
"選項":"オプション","監控":"監視","連接":"接続","可以":"可能",
|
||||
"進程":"プロセス","攔截":"ブロック","引導":"ブート","刪除":"削除",
|
||||
"分區":"パーティション","設定":"設定","關於":"情報","模式":"モード",
|
||||
"提高":"向上","安全":"セキュリティ","顯色":"色","顏色":"色",
|
||||
"主題":"テーマ","回收":"回収","無用":"不要な","導入":"インポート",
|
||||
"風險":"リスク","介面":"インターフェース","核心":"コア","服務":"サービス",
|
||||
"管理":"管理","所有":"すべての","您":"あなた","取消":"キャンセル","未":"未",
|
||||
"垃圾":"ジャンク","位元":"バイト","本機":"PC","停止":"停止",
|
||||
"到":"へ","白名單":"ホワイトリスト","軟體":"ソフトウェア","正在":"",
|
||||
"增加":"追加","移除":"削除","項目":"項目","生成":"生成","稱":"",
|
||||
"複製":"コピー","此":"この","並":"および","全盤":"フル","最新":"最新",
|
||||
"已存在":"既に存在します","數據庫":"データベース","誤報":"誤検知",
|
||||
"高":"高","新":"新","和":"と","可能會":"可能性があります","會":"します",
|
||||
"日誌":"ログ","已":"済み","彈窗":"ポップアップ","要":"する","驅動":"ドライバ",
|
||||
"的":"","顯示":"","個":"","嗎":"","了":"","行":"","立即":"","規則":"ルール",
|
||||
"密鑰":"キー","檢測":"検知","製作":"作成","運行":"実行中",
|
||||
"擴展":"拡張","套件":"キット","自動":"自動","上報":"報告",
|
||||
"分析":"分析","自身":"自身","其他":"その他","配置":"設定",
|
||||
"丟失":"紛失","網站":"ウェブサイト","不兼容":"非互換","列表":"リスト",
|
||||
"竄改":"改ざん","第三方":"サードパーティ","實時":"リアルタイム","查看":"表示",
|
||||
"指定":"指定","清空":"空にする","資源回收桶":"ごみ箱","無法":"できません",
|
||||
"與":"と","當":"時","功能":"機能","異常":"異常","來":"へ",
|
||||
"重置":"リセット","窗口":"ウィンドウ","暫存":"一時","自訂":"カスタム",
|
||||
"不支持":"未対応","共":"合計","秒":"秒","耗時":"所要時間",
|
||||
"沙箱":"サンドボックス","虛擬":"仮想","隔離":"隔離","時":"",
|
||||
"建立":"作成","環境":"環境","化":"","表":"",
|
||||
"達":"到達","上限":"上限","區":"","金鑰":"キー","產品":"製品",
|
||||
"運行庫":".NET CLR","殼碼":"シェルコード","線程":"スレッド","注入":"インジェクション",
|
||||
"前往":"移動","檢查":"確認","可用":"利用可能","靜態":"静的",
|
||||
"版本":"バージョン","是":"","剩餘":"残り","遠控":"遠隔操作"," ":" "},
|
||||
|
||||
"korean_switch": {"開啟":"켜기","關閉":"끄기","开启":"켜기","关闭":"끄기",",":", ",
|
||||
"立即刪除":"즉시 삭제","安全模式":"안전 모드","官方網站":"공식 웹사이트",
|
||||
"腳本":"스크립트","鏈式":"체인","記憶體":"메모리","正在加載":"로딩 중","加載":"로드",
|
||||
"行為":"행위","可疑":"의심스러운","勒索":"랜섬웨어","主要":"주요",
|
||||
"許可條款":"라이선스 약관","惡意":"악성","開發":"개발",
|
||||
"啟用":"활성화","禁用":"비활성화","正在初始化中":"초기화 중","初始化":"초기화",
|
||||
"正在掃描":"스캔 중","正在刪除":"삭제 중","正在追蹤":"추적 중",
|
||||
"最小化到":"최소화","靈敏度":"민감도","正在檢查":"검사 중",
|
||||
"確定要":"정말","引擎靈敏度":"엔진 민감도","更新":"업데이트",
|
||||
"白色主題":"화이트","黃色主題":"옐로우","紅色主題":"레드","語言":"언어",
|
||||
"藍色主題":"블루","綠色主題":"그린","自訂主題":"사용자 지정","黑色主題":"블랙",
|
||||
"特別感謝":"기여자","版本資訊":"버전 정보","通訊":"통신",
|
||||
"註冊":"레지스트리","退出":"종료","檔案":"파일","當前":"현재",
|
||||
"狀態":"상태","掃描":"스캔","工具":"도구","防護":"보호",
|
||||
"失敗":"실패","請":"부탁합니다","路徑":"경로","方式":"방식",
|
||||
"需要":"필요","病毒":"바이러스","選擇":"선택","返回":"뒤로",
|
||||
"受到":"받음","錯誤":"오류","完成":"완료","引擎":"엔진",
|
||||
"托盤":"트레이","圖標":"아이콘","不安全":"안전하지 않음","增強":"강화",
|
||||
"系統":"시스템","雲端":"클라우드","重啟":"재부팅","修復":"복구",
|
||||
"裝置":"장치","發現":"발견","成功":"성공","清理":"정리",
|
||||
"確定":"확인","執行":"실행","警告":"경고","使用":"사용",
|
||||
"網路":"네트워크","變更":"변경","總數":"총계","結束":"종료",
|
||||
"選項":"옵션","監控":"모니터링","連接":"연결","可以":"가능",
|
||||
"進程":"프로세스","攔截":"차단","引導":"부트","刪除":"삭제",
|
||||
"分區":"파티션","設定":"설정","關於":"정보","模式":"모드",
|
||||
"提高":"향상","安全":"보안","顯色":"색상","顏色":"색상",
|
||||
"主題":"테마","回收":"회수","無用":"불필요한","導入":"가져오기",
|
||||
"風險":"위험","介面":"인터페이스","核心":"코어","服務":"서비스",
|
||||
"管理":"관리","所有":"모든","您":"귀하","取消":"취소","未":"미",
|
||||
"垃圾":"정크","位元":"바이트","本機":"PC","停止":"중지",
|
||||
"到":"로","白名單":"화이트리스트","軟體":"소프트웨어","正在":"",
|
||||
"增加":"추가","移除":"제거","項目":"항목","生成":"생성","稱":"",
|
||||
"複製":"복사","此":"이","並":"및","全盤":"전체","最新":"최신",
|
||||
"已存在":"이미 존재함","數據庫":"데이터베이스","誤報":"오탐지",
|
||||
"高":"높음","新":"신규","和":"와","可能會":"할 수 있습니다","會":"합니다",
|
||||
"日誌":"로그","已":"완료","彈窗":"팝업","要":"할","驅動":"드라이버",
|
||||
"的":"","顯示":"","個":"","嗎":"","了":"","行":"","立即":"","規則":"규칙",
|
||||
"密鑰":"키","檢測":"탐지","製作":"제작","運行":"실행 중",
|
||||
"擴展":"확장","套件":"키트","自動":"자동","上報":"보고",
|
||||
"分析":"분석","自身":"자신","其他":"기타","配置":"구성",
|
||||
"丟失":"분실","網站":"웹사이트","不兼容":"호환되지 않음","列表":"목록",
|
||||
"竄改":"변조","第三方":"서드파티","實時":"실시간","查看":"보기",
|
||||
"指定":"지정","清空":"비우기","資源回收桶":"휴지통","無法":"할 수 없음",
|
||||
"與":"와","當":"할 때","功能":"기능","異常":"이상","來":"오다",
|
||||
"重置":"초기화","窗口":"창","暫存":"임시","自訂":"사용자 지정",
|
||||
"不支持":"지원하지 않음","共":"총","秒":"초","耗時":"소요 시간",
|
||||
"沙箱":"샌드박스","虛擬":"가상","隔離":"격리","時":"",
|
||||
"建立":"생성","環境":"환경","化":"","表":"",
|
||||
"達":"도달","上限":"제한","區":"","金鑰":"키","제품":"제품",
|
||||
"運行庫":".NET CLR","殼碼":"셸코드","線程":"스레드","注入":"인젝션",
|
||||
"前往":"이동","檢查":"검사","可用":"사용 가능","靜態":"정적",
|
||||
"版本":"버전","是":"","剩餘":"남은","遠控":"원격 제어"," ":" "},
|
||||
|
||||
"french_switch": {"開啟":"On ","關閉":"Off ","开启":"On ","关闭":"Off ",",":", ",
|
||||
"立即刪除":"Supprimer ","安全模式":"Mode sans échec ","官方網站":"Site officiel ",
|
||||
"腳本":"Script ","鏈式":"Chaîne ","記憶體":"Mémoire ","正在加載":"Chargement ","加載":"Charger ",
|
||||
"行為":"Comportement ","可疑":"Suspect ","勒索":"Ransomware ","主要":"Principal ",
|
||||
"許可條款":"Licence ","惡意":"Malveillant ","開發":"Développeurs ",
|
||||
"啟用":"Activer ","禁用":"Désactiver ","正在初始化中":"Initialisation ","初始化":"Initialiser ",
|
||||
"正在掃描":"Analyse en cours ","正在刪除":"Suppression ","正在追蹤":"Suivi en cours ",
|
||||
"最小化到":"Réduire vers ","靈敏度":"Sensibilité ","正在檢查":"Vérification ",
|
||||
"確定要":"Êtes-vous sûr ","引擎靈敏度":"Sensibilité ","更新":"Mettre à jour ",
|
||||
"白色主題":"Blanc","黃色主題":"Jaune","紅色主題":"Rouge","語言":"Langue ",
|
||||
"藍色主題":"Bleu","綠色主題":"Vert","自訂主題":"Personnalisé","黑色主題":"Noir",
|
||||
"特別感謝":"Contributeurs ","版本資訊":"Information ","通訊":"Connexion ",
|
||||
"註冊":"Registre ","退出":"Quitter ","檔案":"Fichier ","當前":"Actuellement ",
|
||||
"狀態":"État ","掃描":"Analyser ","工具":"Outils ","防護":"Protection ",
|
||||
"失敗":"Échec ","請":"Veuillez ","路徑":"Chemin ","方式":"Méthode ",
|
||||
"需要":"Nécessaire ","病毒":"Virus ","選擇":"Sélectionner ","返回":"Retour ",
|
||||
"受到":"Reçu ","錯誤":"Erreur ","完成":"Terminé ","引擎":"Moteur ",
|
||||
"托盤":"Barre ","圖標":"Icône ","不安全":"Non sécurisé ","增強":"Améliorer ",
|
||||
"系統":"Système ","雲端":"Cloud ","重啟":"Redémarrer ","修復":"Réparer ",
|
||||
"裝置":"Appareil ","發現":"Trouvé ","成功":"Succès ","清理":"Nettoyer ",
|
||||
"確定":"OK ","執行":"Exécuter ","警告":"Avertissement ","使用":"Utiliser ",
|
||||
"網路":"Réseau ","變更":"Modifier ","總數":"Total ","結束":"Fin ",
|
||||
"選項":"Options ","監控":"Surveiller ","連接":"Connecter ","可以":"Peut ",
|
||||
"進程":"Processus ","攔截":"Bloquer ","引導":"Amorçage ","刪除":"Supprimer ",
|
||||
"分區":"Partition ","設定":"Paramètres ","關於":"À propos ","模式":"Mode ",
|
||||
"提高":"Améliorer ","安全":"Sécurité ","顯色":"Couleur ","顏色":"Couleur ",
|
||||
"主題":"Thème ","回收":"Corbeille ","無用":"Inutile ","導入":"Importer ",
|
||||
"風險":"Risque ","介面":"UI ","核心":"Cœur ","服務":"Services ",
|
||||
"管理":"Gérer ","所有":"Tout ","您":"Vous ","取消":"Annuler ","未":"Non ",
|
||||
"垃圾":"Déchet ","位元":"octets ","本機":"PC ","停止":"Arrêter ",
|
||||
"到":"Vers ","白名單":"Liste blanche ","軟體":"Logiciel ","正在":"",
|
||||
"增加":"Ajouter ","移除":"Retirer ","項目":"Éléments ","生成":"Créer ","稱":"",
|
||||
"複製":"Copier ","此":"Ce ","並":"Et ","全盤":"Complet ","最新":"Dernier ",
|
||||
"已存在":"Existe déjà ","數據庫":"Base de données ","誤報":"Faux positif ",
|
||||
"高":"Haut ","新":"Nouveau ","和":"Et ","可能會":"Possible ","會":"Peut ",
|
||||
"日誌":"Journal ","已":"Déjà ","彈窗":"Fenêtre ","要":"À ","驅動":"Pilote ",
|
||||
"的":"","顯示":"","個":"","嗎":"","了":"","行":"","立即":"","規則":"Règle ",
|
||||
"密鑰":"Clé ","檢測":"Détecter ","製作":"Créateur ","運行":"En cours ",
|
||||
"擴展":"Extension ","套件":"Kit ","自動":"Auto ","上報":"Signaler ",
|
||||
"分析":"Analyse ","自身":"Soi-même ","其他":"Autre ","配置":"Config ",
|
||||
"丟失":"Perdu ","網站":"Site ","不兼容":"Incompatible ","列表":"Liste ",
|
||||
"竄改":"Altérer ","第三方":"Tiers ","實時":"Temps réel ","查看":"Voir ",
|
||||
"指定":"Spécifier ","清空":"Vider ","資源回收桶":"Corbeille ","無法":"Impossible ",
|
||||
"與":"Avec ","當":"Quand ","功能":"Fonction ","異常":"Anormal ","來":"Pour ",
|
||||
"重置":"Réinitialiser ","窗口":"Fenêtre ","暫存":"Temp ","自訂":"Personnalisé ",
|
||||
"不支持":"Non supporté ","共":"Total ","秒":"Secondes ","耗時":"Prend ",
|
||||
"沙箱":"Sandbox ","虛擬":"Virtuel ","隔離":"Quarantaine ","時":"",
|
||||
"建立":"Créer ","環境":"Environnement ","化":"","表":"",
|
||||
"達":"Atteint ","上限":"Limite ","區":"","金鑰":"Clé ","產品":"Produit ",
|
||||
"運行庫":".NET CLR ","殼碼":"Shellcode ","線程":"Thread ","注入":"Injecter ",
|
||||
"前往":"Aller ","檢查":"Vérifier ","可用":"Disponible ","靜態":"Statique ",
|
||||
"版本":"Version ","是":"","剩餘":"Restant ","遠控":"Distant "," ":" "},
|
||||
|
||||
"spanish_switch": {"開啟":"On ","關閉":"Off ","开启":"On ","关闭":"Off ",",":", ",
|
||||
"立即刪除":"Eliminar ","安全模式":"Modo seguro ","官方網站":"Sitio web ",
|
||||
"腳本":"Script ","鏈式":"Cadena ","記憶體":"Memoria ","正在加載":"Cargando ","加載":"Cargar ",
|
||||
"行為":"Comportamiento ","可疑":"Sospechoso ","勒索":"Ransomware ","主要":"Principal ",
|
||||
"許可條款":"Licencia ","惡意":"Malicioso ","開發":"Desarrolladores ",
|
||||
"啟用":"Activar ","禁用":"Desactivar ","正在初始化中":"Inicializando ","初始化":"Inicializar ",
|
||||
"正在掃描":"Escaneando ","正在刪除":"Eliminando ","正在追蹤":"Rastreando ",
|
||||
"最小化到":"Minimizar a ","靈敏度":"Sensibilidad ","正在檢查":"Comprobando ",
|
||||
"確定要":"Seguro que ","引擎靈敏度":"Sensibilidad ","更新":"Actualizar ",
|
||||
"白色主題":"Blanco","黃色主題":"Amarillo","紅色主題":"Rojo","語言":"Idioma ",
|
||||
"藍色主題":"Azul","綠色主題":"Verde","自訂主題":"Personalizado","黑色主題":"Negro",
|
||||
"特別感謝":"Colaboradores ","版本資訊":"Información ","通訊":"Conectar ",
|
||||
"註冊":"Registro ","退出":"Salir ","檔案":"Archivo ","當前":"Actualmente ",
|
||||
"狀態":"Estado ","掃描":"Escanear ","工具":"Herramientas ","防護":"Protección ",
|
||||
"失敗":"Fallido ","請":"Por favor ","路徑":"Ruta ","方式":"Método ",
|
||||
"需要":"Necesita ","病毒":"Virus ","選擇":"Seleccionar ","返回":"Volver ",
|
||||
"受到":"Recibido ","錯誤":"Error ","完成":"Completado ","引擎":"Motor ",
|
||||
"托盤":"Bandeja ","圖標":"Icono ","不安全":"Inseguro ","增強":"Mejorar ",
|
||||
"系統":"Sistema ","雲端":"Nube ","重啟":"Reiniciar ","修復":"Reparar ",
|
||||
"裝置":"Dispositivo ","發現":"Encontrado ","成功":"Éxito ","清理":"Limpiar ",
|
||||
"確定":"OK ","執行":"Ejecutar ","警告":"Advertencia ","使用":"Usar ",
|
||||
"網路":"Red ","變更":"Cambiar ","總數":"Total ","結束":"Fin ",
|
||||
"選項":"Opciones ","監控":"Monitor ","連接":"Conectar ","可以":"Puede ",
|
||||
"進程":"Proceso ","攔截":"Bloquear ","引導":"Arranque ","刪除":"Eliminar ",
|
||||
"分區":"Partición ","設定":"Ajustes ","關於":"Acerca de ","模式":"Modo ",
|
||||
"提高":"Mejorar ","安全":"Seguridad ","顯色":"Color ","顏色":"Color ",
|
||||
"主題":"Tema ","回收":"Papelera ","無用":"Inútil ","導入":"Importar ",
|
||||
"風險":"Riesgo ","介面":"UI ","核心":"Núcleo ","服務":"Servicios ",
|
||||
"管理":"Gestionar ","所有":"Todo ","您":"Tú ","取消":"Cancelar ","未":"No ",
|
||||
"垃圾":"Basura ","位元":"bytes ","本機":"PC ","停止":"Detener ",
|
||||
"到":"A ","白名單":"Lista blanca ","軟體":"Software ","正在":"",
|
||||
"增加":"Añadir ","移除":"Eliminar ","項目":"Elementos ","生成":"Crear ","稱":"",
|
||||
"複製":"Copiar ","此":"Este ","並":"Y ","全盤":"Completo ","最新":"Último ",
|
||||
"已存在":"Ya existe ","數據庫":"Base de datos ","誤報":"Falso positivo ",
|
||||
"高":"Alto ","新":"Nuevo ","和":"Y ","可能會":"Posible ","會":"Puede ",
|
||||
"日誌":"Registro ","已":"Ya ","彈窗":"Ventana ","要":"A ","驅動":"Controlador ",
|
||||
"的":"","顯示":"","個":"","嗎":"","了":"","行":"","立即":"","規則":"Regla ",
|
||||
"密鑰":"Clave ","檢測":"Detectar ","製作":"Creador ","運行":"Ejecutando ",
|
||||
"擴展":"Extensión ","套件":"Kit ","自動":"Auto ","上報":"Reportar ",
|
||||
"分析":"Análisis ","自身":"Sí mismo ","其他":"Otro ","配置":"Config ",
|
||||
"丟失":"Perdido ","網站":"Sitio ","不兼容":"Incompatible ","列表":"Lista ",
|
||||
"竄改":"Manipular ","第三方":"Terceros ","實時":"Tiempo real ","查看":"Ver ",
|
||||
"指定":"Especificar ","清空":"Vaciar ","資源回收桶":"Papelera ","無法":"No puede ",
|
||||
"與":"Con ","當":"Cuando ","功能":"Función ","異常":"Anormal ","來":"Para ",
|
||||
"重置":"Restablecer ","窗口":"Ventana ","暫存":"Temp ","自訂":"Personalizado ",
|
||||
"不支持":"No soportado ","共":"Total ","秒":"Segundos ","耗時":"Tarda ",
|
||||
"沙箱":"Sandbox ","虛擬":"Virtual ","隔離":"Cuarentena ","時":"",
|
||||
"建立":"Crear ","環境":"Entorno ","化":"","表":"",
|
||||
"達":"Alcanzado ","上限":"Límite ","區":"","金鑰":"Clave ","產品":"Producto ",
|
||||
"運行庫":".NET CLR ","殼碼":"Shellcode ","線程":"Hilo ","注入":"Inyectar ",
|
||||
"前往":"Ir ","檢查":"Comprobar ","可用":"Disponible ","靜態":"Estático ",
|
||||
"版本":"Versión ","是":"","剩餘":"Restante ","遠控":"Remoto "," ":" "},
|
||||
|
||||
"hindi_switch": {"開啟":"चालू ", "關閉":"बंद ", "开启":"चालू ", "关闭":"बंद ", ",":", ",
|
||||
"立即刪除":"अभी हटाएं ", "安全模式":"सुरक्षित मोड ", "官方網站":"आधिकारिक वेबसाइट ",
|
||||
"腳本":"स्क्रिप्ट ", "鏈式":"चेन ", "記憶體":"मेमोरी ", "正在加載":"लोड हो रहा है ", "加載":"लोड करें ",
|
||||
"行為":"व्यवहार ", "可疑":"संदिग्ध ", "勒索":"रैनसमवेयर ", "主要":"मुख्य ",
|
||||
"許可條款":"लाइसेंस शर्तें ", "惡意":"दुर्भावनापूर्ण ", "開發":"डेवलपर्स ",
|
||||
"啟用":"सक्षम करें ", "禁用":"अक्षम करें ", "正在初始化中":"प्रारंभ हो रहा है ", "初始化":"प्रारंभ करें ",
|
||||
"正在掃描":"स्कैन हो रहा है ", "正在刪除":"हटाया जा रहा है ", "正在追蹤":"ट्रैक किया जा रहा है ",
|
||||
"最小化到":"इसमें छोटा करें ", "靈敏度":"संवेदनशीलता ", "正在檢查":"जांच हो रही है ",
|
||||
"確定要":"क्या आप सुनिश्चित हैं ", "引擎靈敏度":"इंजन संवेदनशीलता ", "更新":"अपडेट करें ",
|
||||
"白色主題":"सफ़ेद", "黃色主題":"पीला", "紅色主題":"लाल", "語言":"भाषा ",
|
||||
"藍色主題":"नीला", "綠色主題":"हरा", "自訂主題":"कस्टम", "黑色主題":"काला",
|
||||
"特別感謝":"योगदानकर्ता ", "版本資訊":"संस्करण जानकारी ", "通訊":"संचार ",
|
||||
"註冊":"रजिस्ट्री ", "退出":"बाहर निकलें ", "檔案":"फ़ाइल ", "當前":"वर्तमान ",
|
||||
"狀態":"स्थिति ", "掃描":"स्कैन ", "工具":"उपकरण ", "防護":"सुरक्षा ",
|
||||
"失敗":"विफल ", "請":"कृपया ", "路徑":"पथ ", "方式":"तरीका ",
|
||||
"需要":"आवश्यक ", "病毒":"वायरस ", "選擇":"चुनें ", "返回":"वापस",
|
||||
"受到":"प्राप्त हुआ ", "錯誤":"त्रुटि ", "完成":"पूरा हुआ ", "引擎":"इंजन ",
|
||||
"托盤":"ट्रे ", "圖標":"आइकन ", "不安全":"असुरक्षित ", "增強":"बढ़ाना ",
|
||||
"系統":"सिस्टम ", "雲端":"क्लाउड ", "重啟":"रीबूट ", "修復":"मरम्मत ",
|
||||
"裝置":"डिवाइस ", "發現":"मिला ", "成功":"सफल ", "清理":"सफाई ",
|
||||
"確定":"ठीक ", "執行":"निष्पादित करें ", "警告":"चेतावनी ", "使用":"उपयोग ",
|
||||
"網路":"नेटवर्क ", "變更":"बदलें ", "總數":"कुल ", "結束":"समाप्त ",
|
||||
"選項":"विकल्प ", "監控":"मॉनिटर ", "連接":"कनेक्ट ", "可以":"सकता है ",
|
||||
"進程":"प्रक्रिया ", "攔截":"ब्लॉक ", "引導":"बूट ", "刪除":"हटाएं ",
|
||||
"分區":"पार्टीशन ", "設定":"सेटिंग्स ", "關於":"के बारे में ", "模式":"मोड ",
|
||||
"提高":"सुधारें ", "安全":"सुरक्षा ", "顯色":"रंग ", "顏色":"रंग ",
|
||||
"主題":"थीम ", "回收":"रीसायकल ", "無用":"बेकार ", "導入":"आयात ",
|
||||
"風險":"जोखिम ", "介面":"यूआई ", "核心":"कोर ", "服務":"सेवाएं ",
|
||||
"管理":"प्रबंधित करें ", "所有":"सभी ", "您":"आप ", "取消":"रद्द करें ", "未":"नहीं ",
|
||||
"垃圾":"कचरा ", "位元":"बाइट ", "本機":"पीसी ", "停止":"रोकें ",
|
||||
"到":"तक ", "白名單":"श्वेत सूची ", "軟體":"सॉफ़्टवेयर ", "正在":"",
|
||||
"增加":"जोड़ें ", "移除":"हटाएं ", "項目":"आइटम ", "生成":"बनाएं ", "稱":"",
|
||||
"複製":"कॉपी ", "此":"यह ", "並":"और ", "全盤":"पूर्ण ", "最新":"नवीनतम ",
|
||||
"已存在":"पहले से मौजूद ", "數據庫":"डेटाबेस ", "誤報":"गलत सूचना ",
|
||||
"高":"उच्च ", "新":"नया ", "和":"और ", "可能會":"संभव ", "會":"सकता है ",
|
||||
"日誌":"लॉग ", "已":"हो चुका ", "彈窗":"विंडो ", "要":"को ", "驅動":"ड्राइवर ",
|
||||
"的":"", "顯示":"", "個":"", "嗎":"", "了":"", "行":"", "立即":"", "規則":"नियम ",
|
||||
"密鑰":"कुंजी ", "檢測":"पता लगाएं ", "製作":"निर्माता ", "運行":"चल रहा है ",
|
||||
"擴展":"एक्सटेंशन ", "套件":"किट ", "自動":"ऑटो ", "上報":"रिपोर्ट ",
|
||||
"分析":"विश्लेषण ", "自身":"स्वयं ", "其他":"अन्य ", "配置":"कॉन्फ़िगर ",
|
||||
"丟失":"खो गया ", "網站":"वेबसाइट ", "不兼容":"असंगत ", "列表":"सूची ",
|
||||
"竄改":"छेड़छाड़ ", "第三方":"थर्ड पार्टी ", "實時":"वास्तविक समय ", "查看":"देखें ",
|
||||
"指定":"निर्दिष्ट करें ", "清空":"खाली करें ", "資源回收桶":"रीसायकल बिन ", "無法":"असमर्थ ",
|
||||
"與":"के साथ ", "當":"जब ", "功能":"कार्य ", "異常":"असामान्य ", "來":"के लिए ",
|
||||
"重置":"रीसेट ", "窗口":"विंडो ", "暫存":"अस्थायी ", "自訂":"कस्टम ",
|
||||
"不支持":"समर्थित नहीं ", "共":"कुल ", "秒":"सेकंड ", "耗時":"लगा समय ",
|
||||
"沙箱":"सैंडबॉक्स ", "虛擬":"आभासी ", "隔離":"संगरोध ", "時":"",
|
||||
"建立":"बनाएं ", "環境":"वातावरण ", "化":"", "表":"",
|
||||
"達":"पहुंच गया ", "上限":"सीमा ", "區":"", "金鑰":"कुंजी ", "產品":"उत्पाद ",
|
||||
"運行庫":".NET CLR ", "殼碼":"शेलकोड ", "線程":"थ्रेड ", "注入":"इंजेक्टर ",
|
||||
"前往":"जाएं ", "檢查":"जांचें ", "可用":"उपलब्ध ", "靜態":"स्थैतिक ",
|
||||
"版本":"संस्करण ", "是":"", "剩餘":"शेष ", "遠控":"रिमोट ", " ":" "},
|
||||
|
||||
"arabic_switch": {"開啟":"تشغيل ", "關閉":"إيقاف ", "开启":"تشغيل ", "关闭":"إيقاف ", ",":", ",
|
||||
"立即刪除":"حذف الآن ", "安全模式":"الوضع الآمن ", "官方網站":"الموقع الرسمي ",
|
||||
"腳本":"برنامج نصي ", "鏈式":"سلسلة ", "記憶體":"الذاكرة ", "正在加載":"جار التحميل ", "加載":"تحميل ",
|
||||
"行為":"سلوك ", "可疑":"مشبوه ", "勒索":"فدية ", "主要":"رئيسي ",
|
||||
"許可條款":"شروط الترخيص ", "惡意":"ضار ", "開發":"المطورين ",
|
||||
"啟用":"تفعيل ", "禁用":"تعطيل ", "正在初始化中":"جار التهيئة ", "初始化":"تهيئة ",
|
||||
"正在掃描":"جار الفحص ", "正在刪除":"جار الحذف ", "正在追蹤":"جار التتبع ",
|
||||
"最小化到":"تصغير إلى ", "靈敏度":"حساسية ", "正在檢查":"جار التحقق ",
|
||||
"確定要":"هل أنت متأكد ", "引擎靈敏度":"حساسية المحرك ", "更新":"تحديث ",
|
||||
"白色主題":"أبيض", "黃色主題":"أصفر", "紅色主題":"أحمر", "語言":"اللغة ",
|
||||
"藍色主題":"أزرق", "綠色主題":"أخضر", "自訂主題":"مخصص", "黑色主題":"أسود",
|
||||
"特別感謝":"المساهمون ", "版本資訊":"معلومات الإصدار ", "通訊":"اتصال ",
|
||||
"註冊":"السجل ", "退出":"خروج ", "檔案":"ملف ", "當前":"الحالي ",
|
||||
"狀態":"الحالة ", "掃描":"فحص ", "工具":"أدوات ", "防護":"حماية ",
|
||||
"失敗":"فشل ", "請":"يرجى ", "路徑":"مسار ", "方式":"طريقة ",
|
||||
"需要":"يحتاج ", "病毒":"فيروس ", "選擇":"تحديد ", "返回":"رجوع",
|
||||
"受到":"تم الاستلام ", "錯誤":"خطأ ", "完成":"مكتمل ", "引擎":"محرك ",
|
||||
"托盤":"صينية ", "圖標":"أيقونة ", "不安全":"غير آمن ", "增強":"تحسين ",
|
||||
"系統":"النظام ", "雲端":"سحابة ", "重啟":"إعادة تشغيل ", "修復":"إصلاح ",
|
||||
"裝置":"جهاز ", "發現":"تم العثور ", "成功":"نجاح ", "清理":"تنظيف ",
|
||||
"確定":"موافق ", "執行":"تنفيذ ", "警告":"تحذير ", "使用":"استخدام ",
|
||||
"網路":"الشبكة ", "變更":"تغيير ", "總數":"الإجمالي ", "結束":"إنهاء ",
|
||||
"選項":"خيارات ", "監控":"مراقبة ", "連接":"اتصال ", "可以":"يمكن ",
|
||||
"進程":"عملية ", "攔截":"حظر ", "引導":"إقلاع ", "刪除":"حذف ",
|
||||
"分區":"قسم ", "設定":"إعدادات ", "關於":"حول ", "模式":"وضع ",
|
||||
"提高":"تحسين ", "安全":"أمان ", "顯色":"لون ", "顏色":"لون ",
|
||||
"主題":"سمة ", "回收":"استرجاع ", "無用":"غير مفيد ", "導入":"استيراد ",
|
||||
"風險":"خطر ", "介面":"واجهة ", "核心":"نواة ", "服務":"خدمات ",
|
||||
"管理":"إدارة ", "所有":"الكل ", "您":"أنت ", "取消":"إلغاء ", "未":"غير ",
|
||||
"垃圾":"مهملات ", "位元":"بايت ", "本機":"الكمبيوتر ", "停止":"إيقاف ",
|
||||
"到":"إلى ", "白名單":"القائمة البيضاء ", "軟體":"برنامج ", "正在":"",
|
||||
"增加":"إضافة ", "移除":"إزالة ", "項目":"عناصر ", "生成":"إنشاء ", "稱":"",
|
||||
"複製":"نسخ ", "此":"هذا ", "並":"و ", "全盤":"كامل ", "最新":"الأحدث ",
|
||||
"已存在":"موجود بالفعل ", "數據庫":"قاعدة البيانات ", "誤報":"إيجابي كاذب ",
|
||||
"高":"عالي ", "新":"جديد ", "和":"و ", "可能會":"محتمل ", "會":"سوف ",
|
||||
"日誌":"سجل ", "已":"بالفعل ", "彈窗":"نافذة ", "要":"إلى ", "驅動":"برنامج تشغيل ",
|
||||
"的":"", "顯示":"", "個":"", "嗎":"", "了":"", "行":"", "立即":"", "規則":"قاعدة ",
|
||||
"密鑰":"مفتاح ", "檢測":"اكتشاف ", "製作":"صانع ", "運行":"قيد التشغيل ",
|
||||
"擴展":"امتداد ", "套件":"مجموعة ", "自動":"تلقائي ", "上報":"إبلاغ ",
|
||||
"分析":"تحليل ", "自身":"نفسه ", "其他":"آخر ", "配置":"تكوين ",
|
||||
"丟失":"مفقود ", "網站":"موقع ", "不兼容":"غير متوافق ", "列表":"قائمة ",
|
||||
"竄改":"تلاعب ", "第三方":"جهة خارجية ", "實時":"الوقت الفعلي ", "查看":"عرض ",
|
||||
"指定":"تحديد ", "清空":"إفراغ ", "資源回收桶":"سلة المهملات ", "無法":"غير قادر ",
|
||||
"與":"مع ", "當":"عندما ", "功能":"وظيفة ", "異常":"شاذ ", "來":"ل ",
|
||||
"重置":"إعادة ضبط ", "窗口":"نافذة ", "暫存":"مؤقت ", "自訂":"مخصص ",
|
||||
"不支持":"غير مدعوم ", "共":"إجمالي ", "秒":"ثواني ", "耗時":"استغرق ",
|
||||
"沙箱":"صندوق الحماية ", "虛擬":"افتراضي ", "隔離":"عزل ", "時":"",
|
||||
"建立":"إنشاء ", "環境":"بيئة ", "化":"", "表":"",
|
||||
"達":"وصل ", "上限":"الحد ", "區":"", "金鑰":"مفتاح ", "產品":"منتج ",
|
||||
"運行庫":".NET CLR ", "殼碼":"رمز قشرة ", "線程":"سلسلة ", "注入":"حقن ",
|
||||
"前往":"الذهاب ", "檢查":"فحص ", "可用":"متاح ", "靜態":"ثابت ",
|
||||
"版本":"إصدار ", "是":"", "剩餘":"المتبقي ", "遠控":"عن بعد ", " ":" "},
|
||||
|
||||
"russian_switch": {"開啟":"Вкл ", "關閉":"Выкл ", "开启":"Вкл ", "关闭":"Выкл ", ",":", ",
|
||||
"立即刪除":"Удалить сейчас ", "安全模式":"Безопасный режим ", "官方網站":"Официальный сайт ",
|
||||
"腳本":"Скрипт ", "鏈式":"Цепочка ", "記憶體":"Память ", "正在加載":"Загрузка ", "加載":"Загрузить ",
|
||||
"行為":"Поведение ", "可疑":"Подозрительный ", "勒索":"Вымогатель ", "主要":"Главный ",
|
||||
"許可條款":"Условия лицензии ", "惡意":"Вредоносный ", "開發":"Разработчики ",
|
||||
"啟用":"Включить ", "禁用":"Отключить ", "正在初始化中":"Инициализация ", "初始化":"Инициализировать ",
|
||||
"正在掃描":"Сканирование ", "正在刪除":"Удаление ", "正在追蹤":"Отслеживание ",
|
||||
"最小化到":"Свернуть в ", "靈敏度":"Чувствительность ", "正在檢查":"Проверка ",
|
||||
"確定要":"Вы уверены, что ", "引擎靈敏度":"Чувствительность движка ", "更新":"Обновить ",
|
||||
"白色主題":"Белый", "黃色主題":"Желтый", "紅色主題":"Красный", "語言":"Язык ",
|
||||
"藍色主題":"Синий", "綠色主題":"Зеленый", "自訂主題":"Пользовательский", "黑色主題":"Черный",
|
||||
"特別感謝":"Участники ", "版本資訊":"Информация о версии ", "通訊":"Связь ",
|
||||
"註冊":"Реестр ", "退出":"Выход ", "檔案":"Файл ", "當前":"Текущий ",
|
||||
"狀態":"Статус ", "掃描":"Сканировать ", "工具":"Инструменты ", "防護":"Защита ",
|
||||
"失敗":"Ошибка ", "請":"Пожалуйста ", "路徑":"Путь ", "方式":"Метод ",
|
||||
"需要":"Требуется ", "病毒":"Вирус ", "選擇":"Выбрать ", "返回":"Назад",
|
||||
"受到":"Получено ", "錯誤":"Ошибка ", "完成":"Завершено ", "引擎":"Движок ",
|
||||
"托盤":"Трей ", "圖標":"Значок ", "不安全":"Небезопасно ", "增強":"Улучшить ",
|
||||
"系統":"Система ", "雲端":"Облако ", "重啟":"Перезагрузка ", "修復":"Восстановить ",
|
||||
"裝置":"Устройство ", "發現":"Найдено ", "成功":"Успех ", "清理":"Очистка ",
|
||||
"確定":"ОК ", "執行":"Выполнить ", "警告":"Предупреждение ", "使用":"Использовать ",
|
||||
"網路":"Сеть ", "變更":"Изменить ", "總數":"Всего ", "結束":"Завершить ",
|
||||
"選項":"Опции ", "監控":"Монитор ", "連接":"Подключить ", "可以":"Можно ",
|
||||
"進程":"Процесс ", "攔截":"Блокировать ", "引導":"Загрузка ", "刪除":"Удалить ",
|
||||
"分區":"Раздел ", "設定":"Настройки ", "關於":"О программе ", "模式":"Режим ",
|
||||
"提高":"Улучшить ", "安全":"Безопасность ", "顯色":"Цвет ", "顏色":"Цвет ",
|
||||
"主題":"Тема ", "回收":"Корзина ", "無用":"Бесполезно ", "導入":"Импорт ",
|
||||
"風險":"Риск ", "介面":"Интерфейс ", "核心":"Ядро ", "服務":"Службы ",
|
||||
"管理":"Управление ", "所有":"Все ", "您":"Вы ", "取消":"Отмена ", "未":"Не ",
|
||||
"垃圾":"Мусор ", "位元":"байт ", "本機":"ПК ", "停止":"Остановить ",
|
||||
"到":"К ", "白名單":"Белый список ", "軟體":"ПО ", "正在":"",
|
||||
"增加":"Добавить ", "移除":"Удалить ", "項目":"Элементы ", "生成":"Создать ", "稱":"",
|
||||
"複製":"Копировать ", "此":"Этот ", "並":"И ", "全盤":"Полный ", "最新":"Последний ",
|
||||
"已存在":"Уже существует ", "數據庫":"База данных ", "誤報":"Ложное срабатывание ",
|
||||
"高":"Высокий ", "新":"Новый ", "和":"И ", "可能會":"Возможно ", "會":"Может ",
|
||||
"日誌":"Журнал ", "已":"Уже ", "彈窗":"Окно ", "要":"Нужно ", "驅動":"Драйвер ",
|
||||
"的":"", "顯示":"", "個":"", "嗎":"", "了":"", "行":"", "立即":"", "規則":"Правило ",
|
||||
"密鑰":"Ключ ", "檢測":"Обнаружить ", "製作":"Создатель ", "運行":"Работает ",
|
||||
"擴展":"Расширение ", "套件":"Набор ", "自動":"Авто ", "上報":"Отчет ",
|
||||
"分析":"Анализ ", "自身":"Сам ", "其他":"Другое ", "配置":"Конфиг ",
|
||||
"丟失":"Утерян ", "網站":"Сайт ", "不兼容":"Несовместимо ", "列表":"Список ",
|
||||
"竄改":"Вмешательство ", "第三方":"Сторонний ", "實時":"Реальное время ", "查看":"Просмотр ",
|
||||
"指定":"Указать ", "清空":"Очистить ", "資源回收桶":"Корзина ", "無法":"Невозможно ",
|
||||
"與":"С ", "當":"Когда ", "功能":"Функция ", "異常":"Аномалия ", "來":"Для ",
|
||||
"重置":"Сброс ", "窗口":"Окно ", "暫存":"Временный ", "自訂":"Пользовательский ",
|
||||
"不支持":"Не поддерживается ", "共":"Всего ", "秒":"Секунд ", "耗時":"Заняло ",
|
||||
"沙箱":"Песочница ", "虛擬":"Виртуальный ", "隔離":"Карантин ", "時":"",
|
||||
"建立":"Создать ", "環境":"Среда ", "化":"", "表":"",
|
||||
"達":"Достигнут ", "上限":"Лимит ", "區":"", "金鑰":"Ключ ", "產品":"Продукт ",
|
||||
"運行庫":".NET CLR ", "殼碼":"Шелл-код ", "線程":"Поток ", "注入":"Инъекция ",
|
||||
"前往":"Перейти ", "檢查":"Проверить ", "可用":"Доступно ", "靜態":"Статический ",
|
||||
"版本":"Версия ", "是":"", "剩餘":"Осталось ", "遠控":"Удаленный ", " ":" "},
|
||||
|
||||
"slovenian_switch": {"開啟":"Vklop ", "關閉":"Izklop ", "开启":"Vklop ", "关闭":"Izklop ", ",":", ",
|
||||
"立即刪除":"Izbriši zdaj ", "安全模式":"Varni način ", "官方網站":"Uradna spletna stran ",
|
||||
"腳本":"Skripta ", "鏈式":"Veriga ", "記憶體":"Pomnilnik ", "正在加載":"Nalaganje ", "加載":"Naloži ",
|
||||
"行為":"Vedenje ", "可疑":"Sumljivo ", "勒索":"Izsiljevalska ", "主要":"Glavni ",
|
||||
"許可條款":"Licenčni pogoji ", "惡意":"Zlonamerno ", "開發":"Razvijalci ",
|
||||
"啟用":"Omogoči ", "禁用":"Onemogoči ", "正在初始化中":"Inicializacija ", "初始化":"Inicializiraj ",
|
||||
"正在掃描":"Skeniranje ", "正在刪除":"Brisanje ", "正在追蹤":"Sledenje ",
|
||||
"最小化到":"Minimiziraj v ", "靈敏度":"Občutljivost ", "正在檢查":"Preverjanje ",
|
||||
"確定要":"Ali ste prepričani ", "引擎靈敏度":"Občutljivost mehanizma ", "更新":"Posodobi ",
|
||||
"白色主題":"Bela", "黃色主題":"Rumena", "紅色主題":"Rdeča", "語言":"Jezik ",
|
||||
"藍色主題":"Modra", "綠色主題":"Zelena", "自訂主題":"Po meri", "黑色主題":"Črna",
|
||||
"特別感謝":"Sodelavci ", "版本資訊":"Informacije o različici ", "通訊":"Povezava ",
|
||||
"註冊":"Register ", "退出":"Izhod ", "檔案":"Datoteka ", "當前":"Trenutno ",
|
||||
"狀態":"Stanje ", "掃描":"Skeniraj ", "工具":"Orodja ", "防護":"Zaščita ",
|
||||
"失敗":"Neuspešno ", "請":"Prosim ", "路徑":"Pot ", "方式":"Način ",
|
||||
"需要":"Potrebno ", "病毒":"Virus ", "選擇":"Izberi ", "返回":"Nazaj",
|
||||
"受到":"Prejeto ", "錯誤":"Napaka ", "完成":"Končano ", "引擎":"Mehanizem ",
|
||||
"托盤":"Pladenj ", "圖標":"Ikona ", "不安全":"Nevarno ", "增強":"Izboljšaj ",
|
||||
"系統":"Sistem ", "雲端":"Oblak ", "重啟":"Ponovni zagon ", "修復":"Popravi ",
|
||||
"裝置":"Naprava ", "發現":"Najdeno ", "成功":"Uspeh ", "清理":"Čiščenje ",
|
||||
"確定":"V redu ", "執行":"Izvedi ", "警告":"Opozorilo ", "使用":"Uporabi ",
|
||||
"網路":"Omrežje ", "變更":"Spremeni ", "總數":"Skupaj ", "結束":"Konec ",
|
||||
"選項":"Možnosti ", "監控":"Nadzor ", "連接":"Poveži ", "可以":"Lahko ",
|
||||
"進程":"Proces ", "攔截":"Blokiraj ", "引導":"Zagon ", "刪除":"Izbriši ",
|
||||
"分區":"Particija ", "設定":"Nastavitve ", "關於":"O programu ", "模式":"Način ",
|
||||
"提高":"Povečaj ", "安全":"Varnost ", "顯色":"Barva ", "顏色":"Barva ",
|
||||
"主題":"Tema ", "回收":"Koš ", "無用":"Nekoristno ", "導入":"Uvozi ",
|
||||
"風險":"Tveganje ", "介面":"Vmesnik ", "核心":"Jedro ", "服務":"Storitve ",
|
||||
"管理":"Upravljaj ", "所有":"Vse ", "您":"Vi ", "取消":"Prekliči ", "未":"Ne ",
|
||||
"垃圾":"Smeti ", "位元":"bajtov ", "本機":"PC ", "停止":"Ustavi ",
|
||||
"到":"V ", "白名單":"Beli seznam ", "軟體":"Programska oprema ", "正在":"",
|
||||
"增加":"Dodaj ", "移除":"Odstrani ", "項目":"Predmeti ", "生成":"Ustvari ", "稱":"",
|
||||
"複製":"Kopiraj ", "此":"To ", "並":"In ", "全盤":"Popolno ", "最新":"Najnovejše ",
|
||||
"已存在":"Že obstaja ", "數據庫":"Podatkovna baza ", "誤報":"Lažni alarm ",
|
||||
"高":"Visoko ", "新":"Novo ", "和":"In ", "可能會":"Možno ", "會":"Bo ",
|
||||
"日誌":"Dnevnik ", "已":"Že ", "彈窗":"Okno ", "要":"V ", "驅動":"Gonilnik ",
|
||||
"的":"", "顯示":"", "個":"", "嗎":"", "了":"", "行":"", "立即":"", "規則":"Pravilo ",
|
||||
"密鑰":"Ključ ", "檢測":"Zaznaj ", "製作":"Ustvarjalec ", "運行":"Se izvaja ",
|
||||
"擴展":"Razširitev ", "套件":"Komplet ", "自動":"Samodejno ", "上報":"Prijavi ",
|
||||
"分析":"Analiza ", "自身":"Samo ", "其他":"Drugo ", "配置":"Konfiguracija ",
|
||||
"丟失":"Izgubljeno ", "網站":"Spletno mesto ", "不兼容":"Nezdružljivo ", "列表":"Seznam ",
|
||||
"竄改":"Spreminjanje ", "第三方":"Tretja oseba ", "實時":"V realnem času ", "查看":"Poglej ",
|
||||
"指定":"Določi ", "清空":"Izprazni ", "資源回收桶":"Koš ", "無法":"Ni mogoče ",
|
||||
"與":"Z ", "當":"Ko ", "功能":"Funkcija ", "異常":"Nenormalno ", "來":"Za ",
|
||||
"重置":"Ponastavi ", "窗口":"Okno ", "暫存":"Začasno ", "自訂":"Po meri ",
|
||||
"不支持":"Ni podprto ", "共":"Skupaj ", "秒":"Sekund ", "耗時":"Trajalo ",
|
||||
"沙箱":"Peskovnik ", "虛擬":"Virtualno ", "隔離":"Karantena ", "時":"",
|
||||
"建立":"Ustvari ", "環境":"Okolje ", "化":"", "表":"",
|
||||
"達":"Doseženo ", "上限":"Omejitev ", "區":"", "金鑰":"Ključ ", "產品":"Izdelek ",
|
||||
"運行庫":".NET CLR ", "殼碼":"Zlonamerna koda ", "線程":"Nit ", "注入":"Vbrizgavanje ",
|
||||
"前往":"Pojdi ", "檢查":"Preveri ", "可用":"Na voljo ", "靜態":"Statično ",
|
||||
"版本":"Različica ", "是":"", "剩餘":"Preostalo ", "遠控":"Oddaljeno ", " ":" "},
|
||||
|
||||
"custom_language_switch": {},
|
||||
|
||||
"white_switch": {
|
||||
"_white": "_black",},
|
||||
"red_switch": {
|
||||
"235, 235, 235": "255, 235, 235",
|
||||
"245, 245, 245": "255, 225, 225",
|
||||
"255, 255, 255": "255, 245, 245",
|
||||
"240, 240, 240": "255, 220, 220",
|
||||
"250, 250, 250": "255, 210, 210",
|
||||
"220, 255, 220": "255, 220, 220",
|
||||
"210, 255, 210": "255, 210, 210",
|
||||
"_white": "_black"
|
||||
},
|
||||
"yellow_switch": {
|
||||
"235, 235, 235": "255, 255, 235",
|
||||
"245, 245, 245": "255, 255, 225",
|
||||
"255, 255, 255": "255, 255, 245",
|
||||
"240, 240, 240": "255, 255, 220",
|
||||
"250, 250, 250": "255, 255, 210",
|
||||
"220, 255, 220": "255, 255, 220",
|
||||
"210, 255, 210": "255, 255, 210",
|
||||
"_white": "_black"
|
||||
},
|
||||
"green_switch": {
|
||||
"235, 235, 235": "235, 255, 235",
|
||||
"245, 245, 245": "225, 255, 225",
|
||||
"255, 255, 255": "245, 255, 245",
|
||||
"240, 240, 240": "220, 255, 220",
|
||||
"250, 250, 250": "210, 255, 210",
|
||||
"_white": "_black"
|
||||
},
|
||||
"blue_switch": {
|
||||
"235, 235, 235": "235, 235, 255",
|
||||
"245, 245, 245": "225, 225, 255",
|
||||
"255, 255, 255": "245, 245, 255",
|
||||
"240, 240, 240": "220, 220, 255",
|
||||
"250, 250, 250": "210, 210, 255",
|
||||
"220, 255, 220": "220, 220, 255",
|
||||
"210, 255, 210": "210, 210, 255",
|
||||
"_white": "_black"
|
||||
},
|
||||
"black_switch": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
+908
-72
@@ -1,84 +1,920 @@
|
||||
import time, json, hashlib, numpy
|
||||
from collections import Counter
|
||||
import os, yara, time, numpy, base64, requests, pefile, math, json, re, datetime
|
||||
import ctypes, ctypes.wintypes, hashlib, onnxruntime
|
||||
|
||||
class ListSimHash:
|
||||
from PIL import Image
|
||||
from io import BytesIO
|
||||
|
||||
####################################################################################################
|
||||
|
||||
class GUID(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("Data1", ctypes.wintypes.DWORD),
|
||||
("Data2", ctypes.wintypes.WORD),
|
||||
("Data3", ctypes.wintypes.WORD),
|
||||
("Data4", ctypes.c_ubyte * 8)
|
||||
]
|
||||
|
||||
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_UNION(ctypes.Union):
|
||||
_fields_ = [
|
||||
("pFile", ctypes.POINTER(WINTRUST_FILE_INFO)),
|
||||
("pCatalog", ctypes.wintypes.LPVOID),
|
||||
("pBlob", ctypes.wintypes.LPVOID),
|
||||
("pSgnr", ctypes.wintypes.LPVOID),
|
||||
("pCert", 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),
|
||||
("u", WINTRUST_DATA_UNION),
|
||||
("dwStateAction", ctypes.wintypes.DWORD),
|
||||
("hWVTStateData", ctypes.wintypes.HANDLE),
|
||||
("pwszURLReference", ctypes.wintypes.LPCWSTR),
|
||||
("dwProvFlags", ctypes.wintypes.DWORD),
|
||||
("dwUIContext", ctypes.wintypes.DWORD),
|
||||
("pSignatureSettings", ctypes.wintypes.LPVOID)
|
||||
]
|
||||
|
||||
####################################################################################################
|
||||
|
||||
class sign_scanner:
|
||||
def __init__(self):
|
||||
self.model = {}
|
||||
self.verify = GUID(0x00AAC56B, 0xCD44, 0x11D0, (ctypes.c_ubyte * 8)(0x8C, 0xC2, 0x00, 0xC0, 0x4F, 0xC2, 0x95, 0xEE))
|
||||
|
||||
def save_model(self, file_name):
|
||||
with open(file_name, 'w') as f:
|
||||
json.dump(self.model, f)
|
||||
print(f"\nModel Is Saved In {file_name}")
|
||||
def init_windll(self, path):
|
||||
for name in path:
|
||||
try:
|
||||
setattr(self, name.lower(), ctypes.WinDLL(name, use_last_error=True))
|
||||
except Exception:
|
||||
pass
|
||||
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 load_model(self, model_data):
|
||||
if isinstance(model_data, str):
|
||||
with open(model_data, 'r') as f:
|
||||
model_data = json.load(f)
|
||||
self.model = model_data
|
||||
####################################################################################################
|
||||
|
||||
def get_model(self, label):
|
||||
return self.model[label]
|
||||
def sign_verify(self, file_path):
|
||||
if os.name != 'nt':
|
||||
return False
|
||||
try:
|
||||
fi = WINTRUST_FILE_INFO()
|
||||
fi.cbStruct = ctypes.sizeof(WINTRUST_FILE_INFO)
|
||||
fi.pcwszFilePath = os.path.abspath(file_path)
|
||||
fi.hFile = None
|
||||
fi.pgKnownSubject = None
|
||||
wt_union = WINTRUST_DATA_UNION()
|
||||
wt_union.pFile = ctypes.pointer(fi)
|
||||
td = WINTRUST_DATA()
|
||||
td.cbStruct = ctypes.sizeof(WINTRUST_DATA)
|
||||
td.pPolicyCallbackData = None
|
||||
td.pSIPClientData = None
|
||||
td.dwUIChoice = 2
|
||||
td.fdwRevocationChecks = 0
|
||||
td.dwUnionChoice = 1
|
||||
td.u = wt_union
|
||||
td.dwStateAction = 0
|
||||
td.hWVTStateData = None
|
||||
td.pwszURLReference = None
|
||||
td.dwProvFlags = 0
|
||||
td.dwUIContext = 0
|
||||
td.pSignatureSettings = None
|
||||
return self.WinVerifyTrust(None, ctypes.byref(self.verify), ctypes.byref(td)) == 0
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def train_model(self, label, data):
|
||||
start = time.time()
|
||||
print(f"Convert {label}")
|
||||
if label not in self.model:
|
||||
self.model[label] = []
|
||||
for i, x in enumerate(data, 1):
|
||||
self.model[label].append(self.build_text(x))
|
||||
used = "{0:.2f}".format(time.time()-start)
|
||||
prefix, suffix = f'{i}/{len(data)}:', f'{used}s'
|
||||
self.progress_bar(i, len(data), prefix, suffix)
|
||||
####################################################################################################
|
||||
|
||||
def build_text(self, content):
|
||||
sums, batch, count = [], [], 0
|
||||
features = dict(Counter(sorted(content)))
|
||||
for f, w in features.items():
|
||||
count += w
|
||||
batch.append(hashlib.sha256(json.dumps(f).encode('utf-8')).digest() * w)
|
||||
if len(batch) >= 10000:
|
||||
sums.append(self.sum_hashes(batch))
|
||||
batch = []
|
||||
if batch:
|
||||
sums.append(self.sum_hashes(batch))
|
||||
combined_sums = numpy.sum(sums, 0)
|
||||
v = numpy.packbits(combined_sums > count / 2).tobytes()
|
||||
return int.from_bytes(v, 'big')
|
||||
class rule_scanner:
|
||||
def __init__(self):
|
||||
self.rules = None
|
||||
self.network = []
|
||||
|
||||
def sum_hashes(self, digests):
|
||||
bitarray = numpy.unpackbits(numpy.frombuffer(b''.join(digests), dtype='>B'))
|
||||
return numpy.sum(numpy.reshape(bitarray, (-1, 256)), 0)
|
||||
def load_path(self, path, callback=None):
|
||||
yara_files = {}
|
||||
for root, _, files in os.walk(path):
|
||||
for file in files:
|
||||
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 progress_bar(self, items, total, prefix='', suffix='', length=50, fill='█'):
|
||||
percent = min(100.0, max(0.0, 100 * (items / float(total))))
|
||||
end_char = '\n' if percent >= 100 else '\r'
|
||||
percent_string = "{0:.2f}".format(percent)
|
||||
filled_length = int(length * items // total)
|
||||
bar = fill * filled_length + ' ' * (length - filled_length)
|
||||
print(f'\r{prefix: <15} |{bar}| {percent_string}% {suffix}', end=end_char)
|
||||
if yara_files:
|
||||
self.compile_all_rules(yara_files)
|
||||
|
||||
def predict_all(self, query):
|
||||
label_similarities = {}
|
||||
query_hash = self.build_text(query)
|
||||
for label in self.model:
|
||||
max_similarity = 0
|
||||
for data_point in self.model[label]:
|
||||
similarity = self.similar(data_point, query_hash)
|
||||
if similarity > max_similarity:
|
||||
max_similarity = similarity
|
||||
label_similarities[label] = max_similarity
|
||||
return label_similarities
|
||||
####################################################################################################
|
||||
|
||||
def predict(self, query):
|
||||
max_similarity, max_label = 0, None
|
||||
query_hash = self.build_text(query)
|
||||
for label in self.model:
|
||||
for data_point in self.model[label]:
|
||||
similarity = self.similar(data_point, query_hash)
|
||||
if similarity > max_similarity:
|
||||
max_similarity, max_label = similarity, label
|
||||
return max_label, max_similarity
|
||||
def load_compiled_rule(self, file):
|
||||
try:
|
||||
self.rules = yara.load(file)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def similar(self, x, y):
|
||||
hamming_distance = bin(x ^ y).count('1')
|
||||
return 1 - hamming_distance / 256
|
||||
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:
|
||||
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 cnn_scanner:
|
||||
def __init__(self):
|
||||
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, 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_file(full_path)
|
||||
|
||||
def load_file(self, file):
|
||||
if file.lower().endswith('.onnx'):
|
||||
try:
|
||||
session = onnxruntime.InferenceSession(file, providers=['CPUExecutionProvider'])
|
||||
self.models.append(session)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
####################################################################################################
|
||||
|
||||
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:
|
||||
with open(file_path, 'rb') as f:
|
||||
return f.read()
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
####################################################################################################
|
||||
|
||||
class pe_scanner:
|
||||
API_CAT_MAPPING = {
|
||||
'ProcessControl': {
|
||||
'CreateProcessA', 'CreateProcessW', 'WinExec', 'ShellExecuteA', 'ShellExecuteW',
|
||||
'ShellExecuteExW', 'ExitProcess', 'TerminateProcess', 'OpenProcess', 'GetExitCodeProcess',
|
||||
'SetThreadPriority', 'GetThreadPriority', 'GetCurrentProcess', 'GetCurrentProcessId',
|
||||
'GetModuleFileNameA', 'GetCommandLineA', 'GetModuleFileNameW', 'GetStartupInfoW'
|
||||
},
|
||||
'Injection': {
|
||||
'VirtualAlloc', 'VirtualAllocEx', 'VirtualProtect', 'VirtualProtectEx', 'WriteProcessMemory',
|
||||
'ReadProcessMemory', 'CreateRemoteThread', 'QueueUserAPC', 'SetThreadContext', 'GetThreadContext',
|
||||
'Wow64SetThreadContext', 'NtUnmapViewOfSection', 'ZwUnmapViewOfSection', 'RtlCreateUserThread',
|
||||
'SetWindowsHookExA', 'SetWindowsHookExW', 'UnhookWindowsHookEx', 'LoadLibraryA', 'LoadLibraryW',
|
||||
'LoadLibraryExA', 'LoadLibraryExW', 'GetProcAddress', 'GetModuleHandleA', 'GetModuleHandleW',
|
||||
'FreeLibrary', 'CreateFileMappingA', 'CreateFileMappingW', 'MapViewOfFile', 'UnmapViewOfSection',
|
||||
'VirtualFree', 'VirtualQuery'
|
||||
},
|
||||
'Synchronization': {
|
||||
'WaitForSingleObject', 'WaitForSingleObjectEx', 'WaitForMultipleObjects', 'WaitForMultipleObjectsEx',
|
||||
'CreateMutexA', 'CreateMutexW', 'OpenMutexW', 'ReleaseMutex', 'CreateEventA', 'CreateEventW',
|
||||
'OpenEventW', 'SetEvent', 'ResetEvent', 'EnterCriticalSection', 'LeaveCriticalSection',
|
||||
'InitializeCriticalSection', 'DeleteCriticalSection', 'Sleep', 'SleepEx',
|
||||
'InitializeCriticalSectionAndSpinCount', 'InterlockedDecrement', 'InterlockedIncrement',
|
||||
'InterlockedExchange', 'InterlockedCompareExchange', 'SetTimer', 'KillTimer'
|
||||
},
|
||||
'MultiThreading': {
|
||||
'CreateThread', 'ResumeThread', 'SuspendThread', 'ExitThread', 'TerminateThread',
|
||||
'GetCurrentThread', 'GetCurrentThreadId', 'TlsAlloc', 'TlsSetValue', 'TlsGetValue',
|
||||
'CreateThreadpoolWork', 'SubmitThreadpoolWork', 'TlsFree'
|
||||
},
|
||||
'Network': {
|
||||
'socket', 'connect', 'send', 'recv', 'bind', 'listen', 'accept', 'gethostbyname', 'getaddrinfo',
|
||||
'WSAStartup', 'WSACleanup', 'WSAIoctl', 'WSASocketA', 'WSASocketW', 'closesocket', 'htons',
|
||||
'InternetOpenA', 'InternetOpenW', 'InternetConnectA', 'InternetConnectW', 'InternetOpenUrlA',
|
||||
'InternetOpenUrlW', 'HttpOpenRequestA', 'HttpOpenRequestW', 'HttpSendRequestA', 'HttpSendRequestW',
|
||||
'InternetReadFile', 'URLDownloadToFileA', 'URLDownloadToFileW', 'DnsQuery_A', 'DnsQuery_W'
|
||||
},
|
||||
'Encryption': {
|
||||
'CryptAcquireContextA', 'CryptAcquireContextW', 'CryptCreateHash', 'CryptHashData',
|
||||
'CryptDeriveKey', 'CryptEncrypt', 'CryptDecrypt', 'CryptDestroyKey', 'CryptDestroyHash',
|
||||
'CryptReleaseContext', 'CryptGenKey', 'CryptImportKey', 'CryptExportKey'
|
||||
},
|
||||
'DataObfuscation': {
|
||||
'RtlDecompressBuffer', 'MultiByteToWideChar', 'WideCharToMultiByte', 'Base64Decode',
|
||||
'CryptDecodeObject', 'IsDBCSLeadByte', 'CharUpperA', 'CharLowerA',
|
||||
'GetStringTypeW', 'LCMapStringW', 'IsValidCodePage', 'DecodePointer', 'EncodePointer'
|
||||
},
|
||||
'FileIO': {
|
||||
'CreateFileA', 'CreateFileW', 'WriteFile', 'ReadFile', 'DeleteFileA', 'DeleteFileW',
|
||||
'CopyFileA', 'CopyFileW', 'MoveFileA', 'MoveFileW', 'FindFirstFileA', 'FindNextFileA',
|
||||
'GetTempPathA', 'GetTempPathW', 'GetTempFileNameA', 'GetTempFileNameW', 'SetFileAttributesA',
|
||||
'SetFileAttributesW', 'DeviceIoControl', 'SetFileTime', 'GetFileSize', 'GetFileSizeEx',
|
||||
'SetFilePointer', 'FlushFileBuffers', 'ConnectNamedPipe', 'PeekNamedPipe',
|
||||
'CloseHandle', 'GetFileType', 'SetStdHandle', 'SetFilePointerEx', 'FindClose',
|
||||
'SetHandleCount', 'SetEndOfFile', 'GetFullPathNameA', 'GetFileAttributesA'
|
||||
},
|
||||
'Registry': {
|
||||
'RegOpenKeyExA', 'RegOpenKeyExW', 'RegSetValueExA', 'RegSetValueExW',
|
||||
'RegCreateKeyExA', 'RegCreateKeyExW', 'RegDeleteKeyA', 'RegDeleteKeyW',
|
||||
'RegEnumValueA', 'RegEnumValueW', 'RegQueryValueExA', 'RegQueryValueExW',
|
||||
'RegDeleteValueA', 'RegDeleteValueW', 'RegCloseKey'
|
||||
},
|
||||
'Services': {
|
||||
'OpenSCManagerA', 'OpenSCManagerW', 'CreateServiceA', 'CreateServiceW',
|
||||
'StartServiceA', 'StartServiceW', 'ControlService', 'DeleteService'
|
||||
},
|
||||
'Privileges': {
|
||||
'AdjustTokenPrivileges', 'LookupPrivilegeValueA', 'LookupPrivilegeValueW',
|
||||
'OpenProcessToken', 'NetUserAdd', 'NetLocalGroupAddMembers', 'IsAdmin',
|
||||
'GetUserNameA', 'GetUserNameW'
|
||||
},
|
||||
'Native': {
|
||||
'RtlUnwind', 'RtlVirtualUnwind', 'RtlCaptureContext', 'RtlLookupFunctionEntry',
|
||||
'NtClose', 'NtQueryInformationProcess', 'RtlAllocateHeap', 'RtlFreeHeap',
|
||||
'GetSystemTimeAsFileTime', 'GetLocalTime', 'GlobalMemoryStatus',
|
||||
'GetVersionExA', 'GetVersionExW', 'GetComputerNameA', 'GetComputerNameW',
|
||||
'GetLastError', 'GetACP', 'RaiseException', 'SetLastError', 'GetEnvironmentStringsW',
|
||||
'FreeEnvironmentStringsW', 'GetLocaleInfoA', 'lstrlenA', 'GetVersion', 'GetSystemInfo',
|
||||
'CompareStringA'
|
||||
},
|
||||
'DotNet': {
|
||||
'_CorExeMain', '_CorDllMain'
|
||||
},
|
||||
'AntiDebug': {
|
||||
'IsDebuggerPresent', 'CheckRemoteDebuggerPresent', 'OutputDebugStringA', 'OutputDebugStringW',
|
||||
'GetTickCount', 'GetTickCount64', 'QueryPerformanceCounter', 'FindWindowA', 'FindWindowW',
|
||||
'EnumWindows', 'EnumChildWindows', 'GetWindowRect', 'GetClientRect', 'SetWindowDisplayAffinity',
|
||||
'UnhandledExceptionFilter', 'SetUnhandledExceptionFilter', 'IsProcessorFeaturePresent',
|
||||
'SetErrorMode', 'GetTimeZoneInformation', 'GetDriveTypeW', 'GetDiskFreeSpaceA'
|
||||
},
|
||||
'Keylogging': {
|
||||
'GetAsyncKeyState', 'GetKeyState', 'GetKeyboardState', 'MapVirtualKeyA', 'MapVirtualKeyW',
|
||||
'ToAscii', 'ToAsciiEx', 'ToUnicode', 'ToUnicodeEx', 'GetKeyNameTextA', 'GetForegroundWindow',
|
||||
'KeybdEvent', 'SendInput', 'MapVirtualKeyExA', 'MapVirtualKeyExW', 'CallNextHookEx'
|
||||
},
|
||||
'Input': {
|
||||
'GetCursorPos', 'SetCursorPos', 'MouseEvent', 'GetDoubleClickTime',
|
||||
'GetCapture', 'SetCapture'
|
||||
},
|
||||
'ScreenCapture': {
|
||||
'BitBlt', 'StretchBlt', 'GetDC', 'GetWindowDC', 'CreateCompatibleDC', 'CreateCompatibleBitmap',
|
||||
'GdipSaveImageToFile', 'PrintWindow', 'GetDesktopWindow', 'CreateDCW', 'CreateDCA',
|
||||
'SelectObject', 'DeleteDC', 'DeleteObject', 'GetDeviceCaps', 'GetSystemMetrics'
|
||||
},
|
||||
'Graphics': {
|
||||
'Direct3DCreate9', 'D3D11CreateDevice'
|
||||
},
|
||||
'Audio': {
|
||||
'WaveInOpen', 'WaveInClose', 'WaveInStart', 'WaveInStop'
|
||||
},
|
||||
'Clipboard': {
|
||||
'OpenClipboard', 'CloseClipboard', 'GetClipboardData', 'SetClipboardData'
|
||||
},
|
||||
'Camera': {
|
||||
'CapCreateCaptureWindowA', 'CapCreateCaptureWindowW'
|
||||
},
|
||||
'Memory': {
|
||||
'HeapAlloc', 'HeapFree', 'HeapSize', 'HeapCreate', 'GetProcessHeap',
|
||||
'LocalAlloc', 'LocalFree', 'GlobalAlloc', 'GlobalFree', 'GlobalUnlock',
|
||||
'HeapDestroy', 'GlobalLock', 'SysFreeString', 'SysAllocStringLen'
|
||||
},
|
||||
'Resource': {
|
||||
'LoadResource', 'SizeofResource', 'LockResource', 'FreeResource', 'FindResourceA'
|
||||
},
|
||||
'WindowControl': {
|
||||
'ShowWindow', 'DestroyWindow', 'TranslateMessage', 'DispatchMessageA', 'GetWindow',
|
||||
'PeekMessageA', 'GetWindowLongA', 'CallWindowProcA', 'SetWindowLongA', 'GetWindowTextA',
|
||||
'ScreenToClient', 'GetActiveWindow', 'CreateWindowExA', 'DefWindowProcA', 'GetMessageA',
|
||||
'RegisterClassA', 'UnregisterClassA', 'MessageBoxA'
|
||||
},
|
||||
'COM': {
|
||||
'CoCreateInstance', 'CoUninitialize', 'CoInitialize'
|
||||
}
|
||||
}
|
||||
|
||||
TARGET_DLLS = {
|
||||
'kernel32.dll', 'user32.dll', 'gdi32.dll', 'advapi32.dll', 'shell32.dll', 'ntdll.dll', 'hal.dll',
|
||||
'ws2_32.dll', 'wsock32.dll', 'wininet.dll', 'winhttp.dll', 'urlmon.dll', 'crypt32.dll', 'bcrypt.dll',
|
||||
'psapi.dll', 'dbghelp.dll', 'imagehlp.dll', 'shlwapi.dll', 'ole32.dll', 'oleaut32.dll', 'comctl32.dll',
|
||||
'mscoree.dll', 'vbscript.dll', 'netapi32.dll', 'iphlpapi.dll', 'wtsapi32.dll', 'version.dll', 'winmm.dll'
|
||||
}
|
||||
|
||||
BASE_SCHEMA = [
|
||||
"FileEntropy", "SectionMeanEntropy", "IsExe", "IsDll", "IsDriver", "Is64Bit",
|
||||
"Machine", "Magic", "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",
|
||||
"TextSectionMaxEntropy", "TextSectionMeanEntropy", "TextSizeRatio",
|
||||
"DataSectionMaxEntropy", "DataSectionMeanEntropy", "DataSizeRatio",
|
||||
"RsrcSectionMaxEntropy", "RsrcSectionMeanEntropy", "RsrcSizeRatio",
|
||||
"SectionCount", "ExecutableSections",
|
||||
"WritableSections", "ReadableSections", "SectionException",
|
||||
"Char_00000020_Count", "Char_00000020_MeanEntropy",
|
||||
"Char_00000040_Count", "Char_00000040_MeanEntropy",
|
||||
"Char_00000080_Count", "Char_00000080_MeanEntropy",
|
||||
"Char_02000000_Count", "Char_02000000_MeanEntropy",
|
||||
"Char_20000000_Count", "Char_20000000_MeanEntropy",
|
||||
"Char_40000000_Count", "Char_40000000_MeanEntropy",
|
||||
"Char_80000000_Count", "Char_80000000_MeanEntropy",
|
||||
"IconCount", "ApiCount", "ExportCount", "DebugCount", "ExceptionCount",
|
||||
"ImportCount", "ImportFunctionCount",
|
||||
"FileDescriptionLength", "FileVersionLength", "ProductNameLength",
|
||||
"ProductVersionLength", "CompanyNameLength", "LegalCopyrightLength",
|
||||
"CommentsLength", "InternalNameLength", "LegalTrademarksLength",
|
||||
"SpecialBuildLength", "PrivateBuildLength",
|
||||
"TrustSigned", "IsDebug", "IsPatched", "IsPrivateBuild", "IsPreRelease",
|
||||
"IsSpecialBuild", "IsAdmin", "IsInstall", "HasTlsCallbacks",
|
||||
"HasInvalidTimestamp", "HasRelocationDirectory", "HasPacked", "FileTimeException"
|
||||
]
|
||||
|
||||
CAT_SCHEMA = [f"Cat_{k}" for k in sorted(API_CAT_MAPPING.keys())]
|
||||
DLL_SCHEMA = [f"Dll_{d.replace('.', '_')}" for d in sorted(TARGET_DLLS)]
|
||||
|
||||
_ALL_APIS = {api for apis in API_CAT_MAPPING.values() for api in apis}
|
||||
API_SCHEMA = [f"Api_{api}" for api in sorted(_ALL_APIS)]
|
||||
SCHEMA = BASE_SCHEMA + CAT_SCHEMA + DLL_SCHEMA + API_SCHEMA
|
||||
|
||||
_API_TO_CATS = {}
|
||||
for _cat, _apis in API_CAT_MAPPING.items():
|
||||
for _api in _apis:
|
||||
if _api not in _API_TO_CATS:
|
||||
_API_TO_CATS[_api] = []
|
||||
_API_TO_CATS[_api].append(_cat)
|
||||
|
||||
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 __init__(self):
|
||||
self.model = None
|
||||
self.input_name = None
|
||||
self.feature_order = []
|
||||
self.signer = sign_scanner()
|
||||
self.signer.init_windll(["wintrust"])
|
||||
|
||||
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)
|
||||
if full_path.endswith('.onnx'):
|
||||
self.load_model(full_path)
|
||||
|
||||
def load_model(self, model_path):
|
||||
if not os.path.exists(model_path):
|
||||
return
|
||||
try:
|
||||
self.model = onnxruntime.InferenceSession(model_path, providers=['CPUExecutionProvider'])
|
||||
self.input_name = self.model.get_inputs()[0].name
|
||||
feat_path = os.path.join(os.path.dirname(model_path), "features.json")
|
||||
|
||||
model_features = []
|
||||
if os.path.exists(feat_path):
|
||||
with open(feat_path, 'r') as f:
|
||||
model_features = json.load(f)
|
||||
else:
|
||||
model_features = [re.sub(r'[^A-Za-z0-9_]+', '', f) for f in self.SCHEMA]
|
||||
|
||||
local_map = {re.sub(r'[^A-Za-z0-9_]+', '', raw_name): raw_name for raw_name in self.SCHEMA}
|
||||
self.feature_order = [local_map.get(req_feat) for req_feat in model_features]
|
||||
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 Exception:
|
||||
return 0.0
|
||||
|
||||
def _safe_div(self, n, d):
|
||||
return float(n) / d if d > 0 else 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.0 for k in self.SCHEMA}
|
||||
pe = None
|
||||
try:
|
||||
fsize = os.path.getsize(file_path)
|
||||
if fsize == 0 or fsize > 268435456:
|
||||
return None
|
||||
with open(file_path, "rb") as f:
|
||||
file_bytes = f.read()
|
||||
pe = pefile.PE(data=file_bytes, 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 = datetime.datetime.now(datetime.timezone.utc).timestamp()
|
||||
fts['HasInvalidTimestamp'] = 1 if (fh.TimeDateStamp < 631152000 or fh.TimeDateStamp > curr_ts + 2592000) else 0
|
||||
fts['FileTimeException'] = 1 if fh.TimeDateStamp == 0 else 0
|
||||
|
||||
if hasattr(pe, 'OPTIONAL_HEADER'):
|
||||
op = pe.OPTIONAL_HEADER
|
||||
fts['Magic'] = getattr(op, 'Magic', 0)
|
||||
fts['MajorLinkerVersion'] = getattr(op, 'MajorLinkerVersion', 0)
|
||||
fts['MinorLinkerVersion'] = getattr(op, 'MinorLinkerVersion', 0)
|
||||
fts['SizeOfCode'] = getattr(op, 'SizeOfCode', 0)
|
||||
fts['SizeOfInitializedData'] = getattr(op, 'SizeOfInitializedData', 0)
|
||||
fts['SizeOfUninitializedData'] = getattr(op, 'SizeOfUninitializedData', 0)
|
||||
fts['AddressOfEntryPoint'] = getattr(op, 'AddressOfEntryPoint', 0)
|
||||
fts['BaseOfCode'] = getattr(op, 'BaseOfCode', 0)
|
||||
fts['ImageBase'] = getattr(op, 'ImageBase', 0)
|
||||
fts['SectionAlignment'] = getattr(op, 'SectionAlignment', 0)
|
||||
fts['FileAlignment'] = getattr(op, 'FileAlignment', 0)
|
||||
fts['MajorOperatingSystemVersion'] = getattr(op, 'MajorOperatingSystemVersion', 0)
|
||||
fts['MinorOperatingSystemVersion'] = getattr(op, 'MinorOperatingSystemVersion', 0)
|
||||
fts['MajorImageVersion'] = getattr(op, 'MajorImageVersion', 0)
|
||||
fts['MinorImageVersion'] = getattr(op, 'MinorImageVersion', 0)
|
||||
fts['MajorSubsystemVersion'] = getattr(op, 'MajorSubsystemVersion', 0)
|
||||
fts['MinorSubsystemVersion'] = getattr(op, 'MinorSubsystemVersion', 0)
|
||||
fts['SizeOfImage'] = getattr(op, 'SizeOfImage', 0)
|
||||
fts['SizeOfHeaders'] = getattr(op, 'SizeOfHeaders', 0)
|
||||
fts['CheckSum'] = getattr(op, 'CheckSum', 0)
|
||||
fts['Subsystem'] = getattr(op, 'Subsystem', 0)
|
||||
fts['DllCharacteristics'] = getattr(op, 'DllCharacteristics', 0)
|
||||
fts['SizeOfStackReserve'] = getattr(op, 'SizeOfStackReserve', 0)
|
||||
fts['SizeOfStackCommit'] = getattr(op, 'SizeOfStackCommit', 0)
|
||||
fts['SizeOfHeapReserve'] = getattr(op, 'SizeOfHeapReserve', 0)
|
||||
fts['SizeOfHeapCommit'] = getattr(op, 'SizeOfHeapCommit', 0)
|
||||
fts['LoaderFlags'] = getattr(op, 'LoaderFlags', 0)
|
||||
fts['NumberOfRvaAndSizes'] = getattr(op, 'NumberOfRvaAndSizes', 0)
|
||||
fts['Is64Bit'] = 1 if fh.Machine in (0x8664, 0xAA64, 0x0200) else 0
|
||||
fts['IsExe'] = 1 if pe.is_exe() else 0
|
||||
fts['IsDll'] = 1 if pe.is_dll() else 0
|
||||
fts['IsDriver'] = 1 if fts['Subsystem'] == 1 else 0
|
||||
if hasattr(op, 'DATA_DIRECTORY'):
|
||||
reloc_idx = pefile.DIRECTORY_ENTRY.get('IMAGE_DIRECTORY_ENTRY_BASERELOC', 5)
|
||||
if len(op.DATA_DIRECTORY) > reloc_idx and op.DATA_DIRECTORY[reloc_idx].Size > 0:
|
||||
fts['HasRelocationDirectory'] = 1
|
||||
|
||||
try:
|
||||
fts['FileEntropy'] = self._calc_entropy(file_bytes)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
sec_entropies = []
|
||||
text_entropies = []
|
||||
data_entropies = []
|
||||
rsrc_entropies = []
|
||||
char_flags = [0x00000020, 0x00000040, 0x00000080, 0x02000000, 0x20000000, 0x40000000, 0x80000000]
|
||||
|
||||
if hasattr(pe, 'sections'):
|
||||
fts['SectionCount'] = len(pe.sections)
|
||||
for section in pe.sections:
|
||||
try:
|
||||
name = section.Name.decode('ascii', 'ignore').strip('\x00')
|
||||
except Exception:
|
||||
name = ""
|
||||
try:
|
||||
s_data = section.get_data()
|
||||
s_entropy = self._calc_entropy(s_data)
|
||||
except Exception:
|
||||
s_data = b""
|
||||
s_entropy = 0.0
|
||||
|
||||
sec_entropies.append(s_entropy)
|
||||
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
|
||||
|
||||
for flag in char_flags:
|
||||
if section.Characteristics & flag:
|
||||
fts[f'Char_{flag:08X}_Count'] += 1
|
||||
fts[f'Char_{flag:08X}_MeanEntropy'] += s_entropy
|
||||
|
||||
ratio = self._safe_div(section.SizeOfRawData, fsize)
|
||||
if name.startswith('.text'):
|
||||
text_entropies.append(s_entropy)
|
||||
fts['TextSizeRatio'] += ratio
|
||||
elif name.startswith('.data'):
|
||||
data_entropies.append(s_entropy)
|
||||
fts['DataSizeRatio'] += ratio
|
||||
elif name.startswith('.rsrc'):
|
||||
rsrc_entropies.append(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
|
||||
|
||||
fts['SectionMeanEntropy'] = self._safe_div(sum(sec_entropies), len(sec_entropies))
|
||||
fts['TextSectionMaxEntropy'] = max(text_entropies) if text_entropies else 0.0
|
||||
fts['TextSectionMeanEntropy'] = self._safe_div(sum(text_entropies), len(text_entropies))
|
||||
fts['DataSectionMaxEntropy'] = max(data_entropies) if data_entropies else 0.0
|
||||
fts['DataSectionMeanEntropy'] = self._safe_div(sum(data_entropies), len(data_entropies))
|
||||
fts['RsrcSectionMaxEntropy'] = max(rsrc_entropies) if rsrc_entropies else 0.0
|
||||
fts['RsrcSectionMeanEntropy'] = self._safe_div(sum(rsrc_entropies), len(rsrc_entropies))
|
||||
|
||||
for flag in char_flags:
|
||||
fts[f'Char_{flag:08X}_MeanEntropy'] = self._safe_div(fts[f'Char_{flag:08X}_MeanEntropy'], fts[f'Char_{flag:08X}_Count'])
|
||||
|
||||
try:
|
||||
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'],
|
||||
pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_TLS']
|
||||
])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if hasattr(pe, 'DIRECTORY_ENTRY_TLS') and hasattr(pe.DIRECTORY_ENTRY_TLS, 'struct'):
|
||||
if getattr(pe.DIRECTORY_ENTRY_TLS.struct, 'AddressOfCallBacks', 0) != 0:
|
||||
fts['HasTlsCallbacks'] = 1
|
||||
|
||||
if hasattr(pe, 'VS_FIXEDFILEINFO') and len(pe.VS_FIXEDFILEINFO) > 0:
|
||||
flags = getattr(pe.VS_FIXEDFILEINFO[0], 'FileFlags', 0)
|
||||
fts['IsDebug'] = 1 if flags & 0x1 else 0
|
||||
fts['IsPreRelease'] = 1 if flags & 0x2 else 0
|
||||
fts['IsPatched'] = 1 if flags & 0x4 else 0
|
||||
fts['IsPrivateBuild'] = 1 if flags & 0x8 else 0
|
||||
fts['IsSpecialBuild'] = 1 if flags & 0x20 else 0
|
||||
|
||||
if hasattr(pe, 'FileInfo'):
|
||||
for fileinfo_list in pe.FileInfo:
|
||||
for fileinfo in fileinfo_list:
|
||||
if getattr(fileinfo, 'name', '') in ('StringFileInfo', b'StringFileInfo'):
|
||||
for st in getattr(fileinfo, 'StringTable', []):
|
||||
for key, val in st.entries.items():
|
||||
try:
|
||||
k = key.decode('utf-8', 'ignore') if isinstance(key, bytes) else str(key)
|
||||
v = val.decode('utf-8', 'ignore') if isinstance(val, bytes) else str(val)
|
||||
length = len(v)
|
||||
if k == 'FileDescription': fts['FileDescriptionLength'] = length
|
||||
elif k == 'FileVersion': fts['FileVersionLength'] = length
|
||||
elif k == 'ProductName': fts['ProductNameLength'] = length
|
||||
elif k == 'ProductVersion': fts['ProductVersionLength'] = length
|
||||
elif k == 'CompanyName': fts['CompanyNameLength'] = length
|
||||
elif k == 'LegalCopyright': fts['LegalCopyrightLength'] = length
|
||||
elif k == 'Comments': fts['CommentsLength'] = length
|
||||
elif k == 'InternalName': fts['InternalNameLength'] = length
|
||||
elif k == 'LegalTrademarks': fts['LegalTrademarksLength'] = length
|
||||
elif k == 'SpecialBuild': fts['SpecialBuildLength'] = length
|
||||
elif k == 'PrivateBuild': fts['PrivateBuildLength'] = length
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
|
||||
fts['ImportCount'] = len(pe.DIRECTORY_ENTRY_IMPORT)
|
||||
for entry in pe.DIRECTORY_ENTRY_IMPORT:
|
||||
if getattr(entry, 'dll', None):
|
||||
try:
|
||||
dll_name = entry.dll.decode('ascii', 'ignore').lower()
|
||||
if dll_name in self.TARGET_DLLS:
|
||||
fts[f"Dll_{dll_name.replace('.', '_')}"] = 1.0
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
imports = getattr(entry, 'imports', [])
|
||||
for imp in imports:
|
||||
fts['ImportFunctionCount'] += 1
|
||||
if not getattr(imp, 'name', None): continue
|
||||
try:
|
||||
func_name = imp.name.decode('ascii', 'ignore')
|
||||
if func_name in self._ALL_APIS:
|
||||
fts[f'Api_{func_name}'] += 1
|
||||
fts['ApiCount'] += 1
|
||||
for cat in self._API_TO_CATS.get(func_name, []):
|
||||
fts[f'Cat_{cat}'] += 1
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT') and hasattr(pe.DIRECTORY_ENTRY_EXPORT, 'symbols'):
|
||||
fts['ExportCount'] = len(pe.DIRECTORY_ENTRY_EXPORT.symbols)
|
||||
|
||||
if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
|
||||
for entry in pe.DIRECTORY_ENTRY_RESOURCE.entries:
|
||||
if getattr(entry, 'id', None) == 3 and hasattr(entry, 'directory'):
|
||||
fts['IconCount'] += len(getattr(entry.directory, 'entries', []))
|
||||
|
||||
if hasattr(pe, 'OPTIONAL_HEADER') and hasattr(pe.OPTIONAL_HEADER, 'DATA_DIRECTORY') and len(pe.OPTIONAL_HEADER.DATA_DIRECTORY) > 3:
|
||||
exc_dir = pe.OPTIONAL_HEADER.DATA_DIRECTORY[3]
|
||||
if exc_dir.Size > 0:
|
||||
fts['ExceptionCount'] = exc_dir.Size // 12 if fts['Machine'] in (0x8664, 0xAA64) else 0
|
||||
|
||||
if hasattr(pe, 'DIRECTORY_ENTRY_DEBUG'):
|
||||
fts['DebugCount'] = len(pe.DIRECTORY_ENTRY_DEBUG)
|
||||
|
||||
for k in fts:
|
||||
fts[k] = self._safe_float(fts[k])
|
||||
|
||||
return fts
|
||||
|
||||
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_data = []
|
||||
for key in self.feature_order:
|
||||
if key:
|
||||
vec_data.append(data.get(key, 0.0))
|
||||
else:
|
||||
vec_data.append(0.0)
|
||||
|
||||
vec = numpy.array(vec_data, 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) and len(result) > 0:
|
||||
prob_dict = result[0]
|
||||
if hasattr(prob_dict, 'get'):
|
||||
prob = float(prob_dict.get(1, prob_dict.get('1', 0.0)))
|
||||
|
||||
elif isinstance(result, numpy.ndarray):
|
||||
if result.ndim == 2 and result.shape[1] > 1:
|
||||
prob = float(result[0][1])
|
||||
|
||||
score = int(prob * 100)
|
||||
if prob > 0.5:
|
||||
return f"General:WinPE/Unknown.{score}!ml", score
|
||||
return False, False
|
||||
except Exception:
|
||||
return False, False
|
||||
|
||||
####################################################################################################
|
||||
|
||||
class cloud_scanner:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def calc_hash(self, file_path, block_size=65536):
|
||||
try:
|
||||
h = hashlib.sha256()
|
||||
with open(file_path, "rb") as f:
|
||||
for chunk in iter(lambda: f.read(block_size), b""):
|
||||
h.update(chunk)
|
||||
return h.hexdigest()
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
####################################################################################################
|
||||
|
||||
def upload_file(self, file_path, api_host, api_key):
|
||||
try:
|
||||
sha256 = self.calc_hash(file_path)
|
||||
if not sha256:
|
||||
return False, None
|
||||
|
||||
base = api_host.rstrip('/')
|
||||
base_headers = {"X-API-Key": api_key, "User-Agent": "PYAS-Client/1.0"}
|
||||
|
||||
def _req(m, ep, files=None, req_timeout=5, **k):
|
||||
try:
|
||||
return requests.request(m, f"{base}{ep}", headers=base_headers, files=files, timeout=req_timeout, **k)
|
||||
except:
|
||||
return None
|
||||
|
||||
r = _req("GET", f"/api/processing_status/{sha256}", req_timeout=15)
|
||||
|
||||
status = 'missing'
|
||||
if r and r.status_code == 200:
|
||||
try:
|
||||
status = r.json().get('status', 'missing')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
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}, req_timeout=30)
|
||||
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, req_timeout, **k):
|
||||
try:
|
||||
return requests.request(m, f"{base}{ep}", headers=headers, timeout=req_timeout, **k)
|
||||
except requests.exceptions.Timeout:
|
||||
return "timeout"
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
timeout_count = 0
|
||||
for _ in range(30):
|
||||
r = _req("GET", f"/api/processing_status/{sha256}", req_timeout=15)
|
||||
|
||||
if r == "timeout" or r is None:
|
||||
timeout_count += 1
|
||||
if timeout_count >= 3:
|
||||
return False
|
||||
time.sleep(1)
|
||||
continue
|
||||
|
||||
st = 'error'
|
||||
if r.status_code == 200:
|
||||
try:
|
||||
st = r.json().get('status', 'error')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if st == 'done':
|
||||
break
|
||||
if st in ['error', 'failed']:
|
||||
return False
|
||||
time.sleep(1)
|
||||
|
||||
r = _req("GET", f"/api/report/{sha256}", req_timeout=30)
|
||||
if r and r != "timeout" and r.status_code == 200:
|
||||
try:
|
||||
data = r.json().get('data', {})
|
||||
res = data.get('detection', {}).get('results', {}).get('PYAS', {})
|
||||
label = res.get('label', 'Unsupport')
|
||||
score = res.get('score', 100)
|
||||
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
|
||||
except Exception:
|
||||
pass
|
||||
return False
|
||||
@@ -1,24 +0,0 @@
|
||||
from subprocess import *
|
||||
import os, re, sys
|
||||
|
||||
class ExtenRules:
|
||||
def __init__(self):
|
||||
self.exten = {}
|
||||
self.pyas = sys.argv[0].replace("\\", "/")
|
||||
self.dir = os.path.dirname(self.pyas)
|
||||
self.exten = os.path.join(self.dir, "Exten")
|
||||
|
||||
def bdc_scan(self, file):
|
||||
if self.exten.replace("\\", "/") not in file.replace("\\", "/"):
|
||||
cmd = f'"{self.exten}\\Bitdefender\\bdc.exe" "{file}"'
|
||||
p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True, universal_newlines=True)
|
||||
for matchs in re.finditer(r'(?P<filename>[^\s]+)\s+infected:\s+(?P<virusname>.+)', p.communicate()[0]):
|
||||
return matchs
|
||||
return False
|
||||
|
||||
def mem_scan(self, p):
|
||||
if self.exten.replace("\\", "/") not in p.exe().replace("\\", "/"):
|
||||
cmd = f'"{self.exten}\\hollows_hunter\\hollows_hunter.exe" /ofilter 2 /pid "{p.pid}"'
|
||||
p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True, universal_newlines=True)
|
||||
return 'Detected' in p.communicate()[0]
|
||||
return False
|
||||
+1546
-1877
File diff suppressed because it is too large.
Load diff
@@ -1,59 +0,0 @@
|
||||
translate_dict = {
|
||||
"zh_TW": {"已开启":"已開啟","已关闭":"已關閉","On":"已開啟","Off":"已關閉"},
|
||||
"zh_CN": {"已開啟":"已开启","已關閉":"已关闭","On":"已开启","Off":"已关闭",
|
||||
"軟體":"软件","檔案":"文件","確定":"确认","設定":"设置","關於":"关于",
|
||||
"錯誤":"错误","實時":"实时","發現":"发现","關閉":"关闭","裝置":"设备",
|
||||
"總數":"总数","註冊":"注册","圖標":"图标","路徑":"路径","網路":"网络",
|
||||
"位元":"字节","彈窗":"弹窗","靈敏":"敏感","複製":"复制","開啟":"开启",
|
||||
"訊":"讯","項":"项","掃":"扫","試":"试","黃":"黄","嗎":"吗","防":"保",
|
||||
"鑰":"钥","當":"当","後":"后","護":"护","導":"导","區":"区","復":"复",
|
||||
"攔":"拦","請":"请","統":"统","刪":"删","進":"进","個":"个","選":"选",
|
||||
"啟":"启","監":"监","並":"并","徑":"径","盤":"盘","隱":"隐","動":"动",
|
||||
"狀":"状","誌":"志","這":"这","會":"会","題":"题","擇":"择","語":"语",
|
||||
"無":"无","顯":"显","變":"变","戶":"户","碼":"码","雲":"云","介":"界",
|
||||
"稱":"称","類":"类","輸":"输","執":"执","數":"数","尋":"寻","網":"网",
|
||||
"詢":"询","製":"制","員":"员","許":"许","條":"条","藍":"蓝","紅":"红",
|
||||
"綠":"绿","態":"态","務":"务","連":"连","檢":"检","測":"测","關":"关",
|
||||
"強":"强","驅":"驱","為":"为","腳":"脚","單":"单","開":"开","擴":"扩",
|
||||
"惡":"恶","據":"据","庫":"库","經":"经","敗":"败","謝":"谢","別":"别",
|
||||
"載":"载","誤":"误","報":"报","鏈":"链","竄":"窜","記憶體":"内存",},
|
||||
"en_US": {"已開啟":"On","已關閉":"Off","已开启":"On","已关闭":"Off",",":", ",
|
||||
"立即刪除":"Delete Now","安全模式":"Safe Mode","官方網站":"Website ",
|
||||
"腳本":"Script ","鏈式":"Chain ","記憶體":"Memory ","加載":"Load ",
|
||||
"行為":"Behavior ","可疑":"Suspicious ","勒索":"Ransom ",
|
||||
"許可條款":"License Terms ","惡意":"Malicious","可疑":"Suspicious",
|
||||
"啟用":"Enable ","禁用":"Disable ","正在初始化中":"Initializing ",
|
||||
"正在掃描":"Scanning ","正在刪除":"Deleting ","最小化到":"Minimize To ",
|
||||
"確定要":"Sure Want To ","靈敏度":"Sensitivity ","更新":"Update ",
|
||||
"白色主題":"White","黃色主題":"Yellow","紅色主題":"Red","語言":"Language ",
|
||||
"藍色主題":"Blue","綠色主題":"Green","自定主題":"Custom","最新":"Latest ",
|
||||
"特別感謝":"Contributors ","版本資訊":"Information","通訊":"Connect ",
|
||||
"註冊表":"Registry ","退出":"Quit ","檔案":"File ","當前":"Currently ",
|
||||
"狀態":"State ","掃描":"Scan ","工具":"Tools ","防護":"Protect ",
|
||||
"失敗":"Failed ","請":"Please ","路徑":"Path ","方式":"Method ",
|
||||
"需要":"Need ","病毒":"Virus ","選擇":"Select ","返回":"Back",
|
||||
"受到":"Been ","錯誤":"Error","完成":"Complete ","引擎":"Engine ",
|
||||
"托盤":"Tray ","圖標":"Icon ","不安全":"Unsafe","增強":"Enhance ",
|
||||
"系統":"System ","雲端":"Cloud ","重啟":"Reboot ","修復":"Repair ",
|
||||
"裝置":"Device ","發現":"Found ","成功":"Success ","清理":"Cleanup ",
|
||||
"確定":"OK","執行":"Execute ","警告":"Warning ","使用":"Use ",
|
||||
"網路":"Network ","變更":"Change ","總數":"Total","結束":"End ",
|
||||
"選項":"Options ","監控":"Monitor ","連接":"Connect ","可以":"To ",
|
||||
"進程":"Process ","攔截":"Block ","引導":"Boot ","刪除":"Delete ",
|
||||
"分區":"Partition ","設定":"Settings","關於":"About","模式":"Mode ",
|
||||
"提高":"Improve ","安全":"Security ","顯色":"Color ","主題":"Themes ",
|
||||
"風險":"Risk ","介面":"GUI ","核心":"Core ","服務":"Services ",
|
||||
"管理":"Manage","所有":"All ","您":"You ","取消":"Cancel ","未":"Not ",
|
||||
"垃圾":"Junk ","位元":"byte ","本機":"Computer ","停止":"Stop ",
|
||||
"增加到":"Add To ","白名單":"White List ","軟體":"Software ","正在":"Start ",
|
||||
"增加":"Add ","移除":"Delete","項目":"Items ","生成":"Create ","稱":"",
|
||||
"複製":"Copy ","開啟":"Open ","此":"This ","並":"And ","全盤":"Full ",
|
||||
"已經在":"Already ","數據庫":"Database ","誤報":"False Positive ",
|
||||
"高":"High ","新":"New ","和":"And ","可能會":"Possible ","會":"Can ",
|
||||
"日誌":"Log","已":"Has ","彈窗":"Window ","要":"To ","驅動":"Driver ",
|
||||
"的":"","顯示":"","個":"","嗎":"","中":"","了":"","行":"","立即":"",
|
||||
"密鑰":"Key ","檢測":"Detect ","製作":"Maker ","運行":"Running",
|
||||
"擴展套件":"Extension Kit ","自動":"Auto ","上報":"Report ","與":"With ",
|
||||
"分析":"Analysis ","自身":"Self ","其他":"Other ","配置":"Config ",
|
||||
"丟失":"Lost ","網站":"Website ","不兼容":"Not Compatible ","追蹤":"Tracking ",
|
||||
"竄改":"Tamper "," ":" "}}
|
||||
+14450
-9866
File diff suppressed because it is too large.
Load diff
@@ -1,11 +0,0 @@
|
||||
slist = [".exe",".dll",".com",".msi",".scr",
|
||||
".js",".bat",".cmd",".ps1",".vbs"]
|
||||
|
||||
alist = [".exe",".dll",".zip",".7z",".rar",
|
||||
".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"]
|
||||
+1
-1
@@ -2,7 +2,7 @@ import pyinstaller_versionfile
|
||||
|
||||
pyinstaller_versionfile.create_versionfile(
|
||||
output_file="versionfile.txt",
|
||||
version='3.1.4',
|
||||
version='3.4.2',
|
||||
company_name="PYAS Security",
|
||||
file_description="Python Antivirus Software",
|
||||
internal_name="PYAS",
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
#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 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_SET_INFORMATION
|
||||
#define THREAD_SET_INFORMATION (0x0020)
|
||||
#endif
|
||||
#ifndef THREAD_SET_THREAD_TOKEN
|
||||
#define THREAD_SET_THREAD_TOKEN (0x0080)
|
||||
#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;
|
||||
|
||||
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 IsTargetProtected(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);
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
#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)) {
|
||||
return STATUS_FLT_DO_NOT_DETACH;
|
||||
}
|
||||
|
||||
if (GlobalData.ServerPort) {
|
||||
FltCloseCommunicationPort(GlobalData.ServerPort);
|
||||
GlobalData.ServerPort = NULL;
|
||||
}
|
||||
|
||||
if (GlobalData.FilterHandle) {
|
||||
FltUnregisterFilter(GlobalData.FilterHandle);
|
||||
GlobalData.FilterHandle = NULL;
|
||||
}
|
||||
|
||||
PsRemoveLoadImageNotifyRoutine(ImageLoadNotify);
|
||||
UninitializeRegistryProtection();
|
||||
UninitializeProcessProtection();
|
||||
|
||||
ExWaitForRundownProtectionRelease(&GlobalData.PortRundown);
|
||||
|
||||
UnloadRules();
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
status = FltRegisterFilter(DriverObject, &FilterRegistration, &GlobalData.FilterHandle);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
UnloadRules();
|
||||
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)) {
|
||||
if (GlobalData.FilterHandle) {
|
||||
FltUnregisterFilter(GlobalData.FilterHandle);
|
||||
GlobalData.FilterHandle = NULL;
|
||||
}
|
||||
UnloadRules();
|
||||
return status;
|
||||
}
|
||||
|
||||
InitializeProcessProtection();
|
||||
InitializeRegistryProtection(DriverObject);
|
||||
PsSetLoadImageNotifyRoutine(ImageLoadNotify);
|
||||
|
||||
status = FltStartFiltering(GlobalData.FilterHandle);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
PsRemoveLoadImageNotifyRoutine(ImageLoadNotify);
|
||||
UninitializeRegistryProtection();
|
||||
UninitializeProcessProtection();
|
||||
|
||||
if (GlobalData.ServerPort) {
|
||||
FltCloseCommunicationPort(GlobalData.ServerPort);
|
||||
GlobalData.ServerPort = NULL;
|
||||
}
|
||||
|
||||
if (GlobalData.FilterHandle) {
|
||||
FltUnregisterFilter(GlobalData.FilterHandle);
|
||||
GlobalData.FilterHandle = NULL;
|
||||
}
|
||||
|
||||
UnloadRules();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
[Version]
|
||||
Signature = "$WINDOWS NT$"
|
||||
Class = ActivityMonitor
|
||||
ClassGuid = {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2}
|
||||
Provider = %ManufacturerName%
|
||||
DriverVer = 12/29/2025,1.0.0.0
|
||||
CatalogFile = PYAS_Driver.cat
|
||||
PnpLockdown = 1
|
||||
|
||||
[DestinationDirs]
|
||||
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 Security"
|
||||
DiskName = "PYAS_Driver Source Disk"
|
||||
ServiceName = "PYAS_Driver"
|
||||
ServiceDescription = "PYAS Security Driver"
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -0,0 +1,33 @@
|
||||
#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)) {
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
#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) {
|
||||
FltReleaseFileNameInformation(nameInfo);
|
||||
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
||||
}
|
||||
|
||||
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) {
|
||||
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)) {
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
#include "DriverCommon.h"
|
||||
|
||||
static PVOID ObRegistrationHandle = NULL;
|
||||
static OB_CALLBACK_REGISTRATION ObRegistration;
|
||||
static OB_OPERATION_REGISTRATION ObCallbacks[2];
|
||||
|
||||
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() != PASSIVE_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;
|
||||
|
||||
if (IsTargetProtected(TargetPid)) {
|
||||
BOOLEAN bIsTrusted = IsProcessTrusted(SourcePid);
|
||||
|
||||
if (bIsTrusted) {
|
||||
if (IsBlacklistedAdminTool(SourcePid)) {
|
||||
bIsTrusted = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (bIsTrusted) 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;
|
||||
}
|
||||
|
||||
static OB_PREOP_CALLBACK_STATUS PreOpenThread(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation) {
|
||||
UNREFERENCED_PARAMETER(RegistrationContext);
|
||||
|
||||
if (OperationInformation->KernelHandle) return OB_PREOP_SUCCESS;
|
||||
|
||||
PETHREAD TargetThread = (PETHREAD)OperationInformation->Object;
|
||||
if (!TargetThread) return OB_PREOP_SUCCESS;
|
||||
|
||||
PEPROCESS TargetProcess = IoThreadToProcess(TargetThread);
|
||||
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;
|
||||
|
||||
if (IsTargetProtected(TargetPid)) {
|
||||
BOOLEAN bIsTrusted = IsProcessTrusted(SourcePid);
|
||||
|
||||
if (bIsTrusted) {
|
||||
if (IsBlacklistedAdminTool(SourcePid)) {
|
||||
bIsTrusted = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (bIsTrusted) return OB_PREOP_SUCCESS;
|
||||
|
||||
ACCESS_MASK DenyMask = THREAD_TERMINATE |
|
||||
THREAD_SUSPEND_RESUME |
|
||||
THREAD_SET_CONTEXT |
|
||||
THREAD_SET_INFORMATION |
|
||||
THREAD_SET_THREAD_TOKEN;
|
||||
|
||||
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;
|
||||
|
||||
ObCallbacks[1].ObjectType = PsThreadType;
|
||||
ObCallbacks[1].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
|
||||
ObCallbacks[1].PreOperation = PreOpenThread;
|
||||
ObCallbacks[1].PostOperation = NULL;
|
||||
|
||||
ObRegistration.Version = OB_FLT_REGISTRATION_VERSION;
|
||||
ObRegistration.OperationRegistrationCount = 2;
|
||||
ObRegistration.Altitude = Altitude;
|
||||
ObRegistration.RegistrationContext = NULL;
|
||||
ObRegistration.OperationRegistration = ObCallbacks;
|
||||
|
||||
return ObRegisterCallbacks(&ObRegistration, &ObRegistrationHandle);
|
||||
}
|
||||
|
||||
VOID UninitializeProcessProtection() {
|
||||
if (ObRegistrationHandle) {
|
||||
ObUnRegisterCallbacks(ObRegistrationHandle);
|
||||
ObRegistrationHandle = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
#include "DriverCommon.h"
|
||||
|
||||
static 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)) {
|
||||
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)) {
|
||||
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();
|
||||
if (!IsProcessTrusted(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)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,795 @@
|
||||
#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 {
|
||||
PEPROCESS Process;
|
||||
ULONG ActivityCount;
|
||||
LARGE_INTEGER LastActivityTime;
|
||||
} RANSOM_TRACKER, * PRANSOM_TRACKER;
|
||||
|
||||
typedef struct _TRUST_CACHE_ENTRY {
|
||||
PEPROCESS Process;
|
||||
BOOLEAN IsTrusted;
|
||||
LARGE_INTEGER CacheTime;
|
||||
} TRUST_CACHE_ENTRY, * PTRUST_CACHE_ENTRY;
|
||||
|
||||
static RANSOM_TRACKER RansomTrackers[MAX_TRACKERS];
|
||||
static TRUST_CACHE_ENTRY TrustCache[TRUST_CACHE_SIZE];
|
||||
static FAST_MUTEX TrustCacheLock;
|
||||
static BOOLEAN g_CacheInitialized = FALSE;
|
||||
|
||||
static ERESOURCE RuleLock;
|
||||
static PRULE_NODE g_RegistryBlockList = NULL;
|
||||
static PRULE_NODE g_RegistryTrustedList = NULL;
|
||||
static PRULE_NODE g_ProcessTrustedPaths = NULL;
|
||||
static PRULE_NODE g_ProcessExploitable = NULL;
|
||||
static PRULE_NODE g_FileProtectedPaths = NULL;
|
||||
static PRULE_NODE g_FileExceptionPaths = NULL;
|
||||
static 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"*\\Windows\\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() != PASSIVE_LEVEL) return FALSE;
|
||||
|
||||
PEPROCESS Process = NULL;
|
||||
if (!NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &Process))) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_CacheInitialized) {
|
||||
ExAcquireFastMutex(&TrustCacheLock);
|
||||
ULONG Hash = ((ULONG)(ULONG_PTR)ProcessId) & (TRUST_CACHE_SIZE - 1);
|
||||
if (TrustCache[Hash].Process == Process) {
|
||||
LARGE_INTEGER Now;
|
||||
KeQuerySystemTime(&Now);
|
||||
if ((Now.QuadPart - TrustCache[Hash].CacheTime.QuadPart) < (TRUST_CACHE_TTL_SEC * 10000000LL)) {
|
||||
BOOLEAN cachedResult = TrustCache[Hash].IsTrusted;
|
||||
ExReleaseFastMutex(&TrustCacheLock);
|
||||
ObDereferenceObject(Process);
|
||||
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].Process = Process;
|
||||
TrustCache[Hash].IsTrusted = isTrusted;
|
||||
KeQuerySystemTime(&TrustCache[Hash].CacheTime);
|
||||
ExReleaseFastMutex(&TrustCacheLock);
|
||||
}
|
||||
|
||||
if (imageFileName) ExFreePool(imageFileName);
|
||||
ObDereferenceObject(Process);
|
||||
return isTrusted;
|
||||
}
|
||||
|
||||
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() != PASSIVE_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;
|
||||
}
|
||||
|
||||
PEPROCESS Process = NULL;
|
||||
if (!NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &Process))) {
|
||||
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->Process == Process) {
|
||||
Tracker = Current;
|
||||
break;
|
||||
}
|
||||
|
||||
BOOLEAN IsExpired = FALSE;
|
||||
if (Current->Process != NULL) {
|
||||
LARGE_INTEGER Diff;
|
||||
Diff.QuadPart = Now.QuadPart - Current->LastActivityTime.QuadPart;
|
||||
if (Diff.QuadPart > (RANSOM_TIME_WINDOW_MS * 10000LL)) {
|
||||
IsExpired = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((Current->Process == NULL || IsExpired) && !CandidateSlot) {
|
||||
CandidateSlot = Current;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Tracker) {
|
||||
if (CandidateSlot) {
|
||||
Tracker = CandidateSlot;
|
||||
}
|
||||
else {
|
||||
Tracker = LruSlot;
|
||||
}
|
||||
|
||||
Tracker->Process = Process;
|
||||
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);
|
||||
ObDereferenceObject(Process);
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
{
|
||||
"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\\*",
|
||||
|
||||
"*\\mouclass",
|
||||
"*\\kbdclass",
|
||||
"*\\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", ".xml", ".sql", ".db"
|
||||
]
|
||||
}
|
||||
@@ -1,176 +1,197 @@
|
||||
# PYAS (Python Antivirus Software)
|
||||
# PYAS
|
||||
|
||||

|
||||
Antivirus software written in Python and C++ that blocks threats through deep learning and behavioral monitoring!
|
||||
|
||||
## Readme Language
|
||||
|
||||
[繁體中文](https://github.com/87owo/PYAS/blob/main/README_zh_TW.md) ,
|
||||
[简体中文](https://github.com/87owo/PYAS/blob/main/README_zh_CN.md)
|
||||
|
||||
## File Information
|
||||
|
||||
PYAS.py -> Main PYAS Program (including animation, scanning, protection functions, etc.)
|
||||
|
||||
PYAS_Engine.py -> Conversion Database (used to convert database dict and list to and from each other)
|
||||
|
||||
PYAS_Extension.py -> File Extension (including scanned file extensions and common file extensions)
|
||||
|
||||
PYAS_Model.* -> Virus Database (the virus database must be placed in the same directory)
|
||||
|
||||
PYAS_Interface.py -> PyQt5 Interface (designed by QT designer, must be matched with the main program)
|
||||
|
||||
PYAS_Resource.py -> PyQt5 Resource (status pictures, icon packages, button icons, etc.)
|
||||
|
||||
PYAS_Language.py -> Translate Dict (Traditional Chinese, Simplified Chinese, English)
|
||||
|
||||
PYAS_Version.py -> Pyinstaller Info (file information, version information, original name, etc.)
|
||||
|
||||
## Dir Information
|
||||
|
||||
```
|
||||
PYAS/
|
||||
├── Driver/
|
||||
│ ├── PYAS_Driver.sys
|
||||
│ └── ...
|
||||
│
|
||||
├── Model/
|
||||
│ ├── PYAS_Model.json
|
||||
│ ├── PYAS_Model.txt
|
||||
│ └── ...
|
||||
│
|
||||
├── Rules/
|
||||
│ ├── Yara_Rules.yar
|
||||
│ ├── Compile_Rules.yrc
|
||||
│ └── ...
|
||||
│
|
||||
├── PYAS.py
|
||||
├── PYAS_Engine.py
|
||||
└── ...
|
||||
```
|
||||
<img width="2245" height="1477" alt="PYAS_UI" src="https://github.com/user-attachments/assets/87d40261-7655-49ad-a19c-1ffcca60584f" />
|
||||
|
||||
## Requirements
|
||||
|
||||
Use pip install requirements to install import module
|
||||
Python 3.10 is recommended. Other Python versions may require different pip commands.
|
||||
|
||||
```
|
||||
psutil==5.9.5
|
||||
pefile==2023.2.7
|
||||
requests==2.31.0
|
||||
pyperclip==1.8.2
|
||||
pywin32==306
|
||||
PyQt5==5.15.9
|
||||
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
|
||||
```
|
||||
|
||||
## Pefile Scanning
|
||||
## File Information
|
||||
|
||||
Get the pefile file function import table for scanning
|
||||
The following lists the storage locations of all relevant code and other related documents.
|
||||
|
||||
```
|
||||
import pefile
|
||||
|
||||
def pe_scan(file):
|
||||
try:
|
||||
fn = []
|
||||
with pefile.PE(file) as pe:
|
||||
for entry in pe.DIRECTORY_ENTRY_IMPORT:
|
||||
for func in entry.imports:
|
||||
try:
|
||||
fn.append(str(func.name, "utf-8"))
|
||||
except:
|
||||
pass
|
||||
if fn in known_malicious_list:
|
||||
return "Virus"
|
||||
return "Safe"
|
||||
return "Unknown"
|
||||
except Exception as e:
|
||||
return f"Error: {e}"
|
||||
|
||||
info = pe_scan("path to file")
|
||||
print(info)
|
||||
PYAS/
|
||||
├── Engine/
|
||||
│ ├── Pattern/
|
||||
│ │ ├── convert.py # Convert executable files or other files to images
|
||||
│ │ ├── train.py # TensorFlow CNN model training complete code
|
||||
│ │ └── ... # Other models folders and files
|
||||
│ │
|
||||
│ ├── Heuristic/
|
||||
│ │ ├── rules.yar # Yara virus signature rule matching
|
||||
│ │ └── ... # Other rules folders and files
|
||||
│ └── ... # Other engine folders and files
|
||||
│
|
||||
├── Plugins/
|
||||
│ └── Filter/
|
||||
│ │ ├── 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
|
||||
├── PYAS_Interface.py # User interface components and event handling
|
||||
├── PYAS_Resource.py # Static image and icon resource management
|
||||
├── PYAS_Version.py # Version metadata for packaging and updates
|
||||
└── ... # Other supplementary folders and files
|
||||
```
|
||||
|
||||
## Process Detect
|
||||
## Architecture diagram
|
||||
|
||||
Show the new process name, file path, cmd line, pid
|
||||
PYAS Security antivirus software general architecture diagram.
|
||||
|
||||
```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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
```
|
||||
import psutil, time
|
||||
|
||||
def proc_detect():
|
||||
existing_process = set()
|
||||
for p in psutil.process_iter():
|
||||
existing_process.add(p.pid)
|
||||
while True:
|
||||
time.sleep(0.1)
|
||||
new_process = set()
|
||||
for p in psutil.process_iter():
|
||||
new_process.add(p.pid)
|
||||
for pid in new_process - existing_process:
|
||||
try:
|
||||
p = psutil.Process(pid)
|
||||
name, file, cmd = p.name(), p.exe(), p.cmdline()
|
||||
print(f"Name: {name}")
|
||||
print(f"File: {file}")
|
||||
print(f"Pid: {p.pid}")
|
||||
print(f"Cmd: {cmd}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
existing_process = new_process
|
||||
|
||||
proc_detect()
|
||||
```
|
||||
|
||||
## File Detect
|
||||
|
||||
Monitor file changes under the specified path
|
||||
|
||||
```
|
||||
import os, win32file, win32con
|
||||
|
||||
def file_detect(path):
|
||||
hDir = win32file.CreateFile(path,win32con.GENERIC_READ,win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE|win32con.FILE_SHARE_DELETE,None,win32con.OPEN_EXISTING,win32con.FILE_FLAG_BACKUP_SEMANTICS,None)
|
||||
while True:
|
||||
for action, file in win32file.ReadDirectoryChangesW(hDir,10485760,True,win32con.FILE_NOTIFY_CHANGE_FILE_NAME|win32con.FILE_NOTIFY_CHANGE_DIR_NAME|win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES|win32con.FILE_NOTIFY_CHANGE_SIZE|win32con.FILE_NOTIFY_CHANGE_LAST_WRITE|win32con.FILE_NOTIFY_CHANGE_SECURITY,None,None):
|
||||
try:
|
||||
fpath = os.path.join(path, file)
|
||||
if action == 1:
|
||||
print(f"File Create: {fpath}")
|
||||
elif action == 2:
|
||||
print(f"File Delete: {fpath}")
|
||||
elif action == 3:
|
||||
print(f"File Modify: {fpath}")
|
||||
elif action == 4:
|
||||
print(f"File Rename: {fpath}")
|
||||
elif action == 5:
|
||||
print(f"File Rename: {fpath}")
|
||||
except:
|
||||
pass
|
||||
|
||||
file_detect("path")
|
||||
```
|
||||
|
||||
## Official Website
|
||||
|
||||
https://pyantivirus.wixsite.com/pyas
|
||||
|
||||
https://github.com/87owo/PYAS
|
||||
|
||||
## PYAS Driver
|
||||
|
||||
https://github.com/0sha0/PYAS_Protection
|
||||
|
||||
## MIT license
|
||||
|
||||
https://github.com/87owo/PYAS/blob/main/LICENSE.md
|
||||
|
||||
## Support System
|
||||
|
||||
Windows 8.1, 10, 11 (64-bit), Ram 500MB, Rom 200MB or higher
|
||||
| Config | Permissions | System version | Processor | Memory | Storage |
|
||||
|-----------|---------------|----------------------|-----------|--------|---------|
|
||||
| Minimum | Administrator | >= Windows 10 (20H1) | 1 GHz | 200MB | 100MB |
|
||||
| Recommend | Administrator | >= Windows 10 (21H2) | 3 GHz | 500MB | 200MB |
|
||||
|
||||
Other systems may experience software malfunctions or crash
|
||||
## Packaged Releases
|
||||
|
||||
## Special Thanks
|
||||
Download the installer. If it is incompatible with your system, you can repackage it yourself.
|
||||
|
||||
Wix, 0sha0, mtkiao129, AV-T Team of LisectGroup
|
||||
Packaged Download: https://github.com/87owo/PYAS/releases
|
||||
|
||||
Copyright© 2020~2024 PYAS Security By 87owo
|
||||
## Official Website
|
||||
|
||||
If you are interested in this project, you can visit the website to see other related content.
|
||||
|
||||
Source Available : https://github.com/87owo/PYAS
|
||||
|
||||
Official Website : https://pyas-security.com/antivirus
|
||||
|
||||
Online Analyze : https://pyas-security.com/analyze
|
||||
|
||||
## Project License
|
||||
|
||||
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
|
||||
-171
@@ -1,171 +0,0 @@
|
||||
# PYAS (Python 杀毒软件)
|
||||
|
||||

|
||||
|
||||
## 文件信息
|
||||
|
||||
PYAS.py -> PYAS主程式(包括动画、扫描、保护功能等)
|
||||
|
||||
PYAS_Engine.py -> 转换资料库(用于相互转换资料库字典和清单)
|
||||
|
||||
PYAS_Extension.py -> 副文件名(包括扫描文件副文件名和常用副文件名)
|
||||
|
||||
PYAS_Model.* -> 病毒库(病毒库必须放在同一目录下)
|
||||
|
||||
PYAS_Interface.py -> PyQt5界面(由QT设计师设计,必须与主程式相符)
|
||||
|
||||
PYAS_Resource.py -> PyQt5资源(状态图片、图示包、按钮图示等)
|
||||
|
||||
PYAS_Language.py -> 翻译字典(繁体中文、简体中文、英文)
|
||||
|
||||
PYAS_Version.py -> Pyinstaller资讯(文件资讯、版本资讯、原名等)
|
||||
|
||||
## 目录信息
|
||||
|
||||
```
|
||||
PYAS/
|
||||
├── Driver/
|
||||
│ ├── PYAS_Driver.sys
|
||||
│ └── ...
|
||||
│
|
||||
├── Model/
|
||||
│ ├── PYAS_Model.json
|
||||
│ ├── PYAS_Model.txt
|
||||
│ └── ...
|
||||
│
|
||||
├── Rules/
|
||||
│ ├── Yara_Rules.yar
|
||||
│ ├── Compile_Rules.yrc
|
||||
│ └── ...
|
||||
│
|
||||
├── PYAS.py
|
||||
├── PYAS_Engine.py
|
||||
└── ...
|
||||
```
|
||||
|
||||
## 安装要求
|
||||
|
||||
使用 pip install requirements 来安装需要的模组
|
||||
|
||||
```
|
||||
psutil==5.9.5
|
||||
pefile==2023.2.7
|
||||
requests==2.31.0
|
||||
pyperclip==1.8.2
|
||||
pywin32==306
|
||||
PyQt5==5.15.9
|
||||
```
|
||||
|
||||
## 文件扫描
|
||||
|
||||
取得pefile文件函数导入表进行扫描
|
||||
|
||||
```
|
||||
import pefile
|
||||
|
||||
def pe_scan(file):
|
||||
try:
|
||||
fn = []
|
||||
with pefile.PE(file) as pe:
|
||||
for entry in pe.DIRECTORY_ENTRY_IMPORT:
|
||||
for func in entry.imports:
|
||||
try:
|
||||
fn.append(str(func.name, "utf-8"))
|
||||
except:
|
||||
pass
|
||||
if fn in known_malicious_list:
|
||||
return "Virus"
|
||||
return "Safe"
|
||||
return "Unknown"
|
||||
except Exception as e:
|
||||
return f"Error: {e}"
|
||||
|
||||
info = pe_scan("path to file")
|
||||
print(info)
|
||||
```
|
||||
|
||||
## 进程监控
|
||||
|
||||
显示新进程名称、文件路径、cmd 行、pid
|
||||
|
||||
```
|
||||
import psutil, time
|
||||
|
||||
def proc_detect():
|
||||
existing_process = set()
|
||||
for p in psutil.process_iter():
|
||||
existing_process.add(p.pid)
|
||||
while True:
|
||||
time.sleep(0.1)
|
||||
new_process = set()
|
||||
for p in psutil.process_iter():
|
||||
new_process.add(p.pid)
|
||||
for pid in new_process - existing_process:
|
||||
try:
|
||||
p = psutil.Process(pid)
|
||||
name, file, cmd = p.name(), p.exe(), p.cmdline()
|
||||
print(f"Name: {name}")
|
||||
print(f"File: {file}")
|
||||
print(f"Pid: {p.pid}")
|
||||
print(f"Cmd: {cmd}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
existing_process = new_process
|
||||
|
||||
proc_detect()
|
||||
```
|
||||
|
||||
## 文件监控
|
||||
|
||||
监控指定路径下的文件变化
|
||||
|
||||
```
|
||||
import os, win32file, win32con
|
||||
|
||||
def file_detect(path):
|
||||
hDir = win32file.CreateFile(path,win32con.GENERIC_READ,win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE|win32con.FILE_SHARE_DELETE,None,win32con.OPEN_EXISTING,win32con.FILE_FLAG_BACKUP_SEMANTICS,None)
|
||||
while True:
|
||||
for action, file in win32file.ReadDirectoryChangesW(hDir,10485760,True,win32con.FILE_NOTIFY_CHANGE_FILE_NAME|win32con.FILE_NOTIFY_CHANGE_DIR_NAME|win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES|win32con.FILE_NOTIFY_CHANGE_SIZE|win32con.FILE_NOTIFY_CHANGE_LAST_WRITE|win32con.FILE_NOTIFY_CHANGE_SECURITY,None,None):
|
||||
try:
|
||||
fpath = os.path.join(path, file)
|
||||
if action == 1:
|
||||
print(f"File Create: {fpath}")
|
||||
elif action == 2:
|
||||
print(f"File Delete: {fpath}")
|
||||
elif action == 3:
|
||||
print(f"File Modify: {fpath}")
|
||||
elif action == 4:
|
||||
print(f"File Rename: {fpath}")
|
||||
elif action == 5:
|
||||
print(f"File Rename: {fpath}")
|
||||
except:
|
||||
pass
|
||||
|
||||
file_detect("path")
|
||||
```
|
||||
|
||||
## 官方网页
|
||||
|
||||
https://pyantivirus.wixsite.com/pyas
|
||||
|
||||
https://github.com/87owo/PYAS
|
||||
|
||||
## 开源协议
|
||||
|
||||
https://github.com/87owo/PYAS/blob/main/LICENSE.md
|
||||
|
||||
## 驱动程序
|
||||
|
||||
https://github.com/0sha0/PYAS_Protection
|
||||
|
||||
## 支援系统
|
||||
|
||||
Windows 8.1, 10, 11 (64-bit), 内存 500MB, 存储 200MB 或更高
|
||||
|
||||
其他系统或版本可能会遇到软体功能故障或程序崩溃
|
||||
|
||||
## 特别感谢
|
||||
|
||||
360, Wix, VirusShare, mtkiao129, AV-T Team of LisectGroup
|
||||
|
||||
Copyright© 2020~2024 PYAS Security By 87owo
|
||||
-169
@@ -1,169 +0,0 @@
|
||||
# PYAS (Python 防毒軟體)
|
||||
|
||||

|
||||
|
||||
## 檔案資訊
|
||||
|
||||
PYAS.py -> PYAS主程式(包括動畫、掃描、保護功能等)
|
||||
|
||||
PYAS_Engine.py -> 轉換資料庫(用於相互轉換資料庫字典和清單)
|
||||
|
||||
PYAS_Extension.py -> 檔案副檔名(包括掃描檔案副檔名和常用檔案副檔名)
|
||||
|
||||
PYAS_Model.* -> 病毒庫(病毒庫必須放在同一目錄下)
|
||||
|
||||
PYAS_Interface.py -> PyQt5 Interface(由QT設計師設計,必須與主程式相符)
|
||||
|
||||
PYAS_Resource.py -> PyQt5資源(狀態圖片、圖示包、按鈕圖示等)
|
||||
|
||||
PYAS_Language.py -> 翻譯字典(繁體中文、簡體中文、英文)
|
||||
|
||||
PYAS_Version.py -> Pyinstaller Info(檔案資訊、版本資訊、原名等)
|
||||
|
||||
## 目錄資訊
|
||||
|
||||
```
|
||||
PYAS/
|
||||
├── Driver/
|
||||
│ ├── PYAS_Driver.sys
|
||||
│ └── ...
|
||||
│
|
||||
├── Model/
|
||||
│ ├── PYAS_Model.json
|
||||
│ ├── PYAS_Model.txt
|
||||
│ └── ...
|
||||
│
|
||||
├── Rules/
|
||||
│ ├── Yara_Rules.yar
|
||||
│ ├── Compile_Rules.yrc
|
||||
│ └── ...
|
||||
│
|
||||
├── PYAS.py
|
||||
├── PYAS_Engine.py
|
||||
└── ...
|
||||
```
|
||||
|
||||
## 安裝要求
|
||||
|
||||
使用 pip install requirements 來安裝需要的模組
|
||||
|
||||
```
|
||||
psutil==5.9.5
|
||||
pefile==2023.2.7
|
||||
requests==2.31.0
|
||||
pyperclip==1.8.2
|
||||
pywin32==306
|
||||
PyQt5==5.15.9
|
||||
```
|
||||
|
||||
## 檔案掃描
|
||||
|
||||
取得pefile檔案函數導入表進行掃描
|
||||
|
||||
```
|
||||
import pefile
|
||||
|
||||
def pe_scan(file):
|
||||
try:
|
||||
fn = []
|
||||
with pefile.PE(file) as pe:
|
||||
for entry in pe.DIRECTORY_ENTRY_IMPORT:
|
||||
for func in entry.imports:
|
||||
try:
|
||||
fn.append(str(func.name, "utf-8"))
|
||||
except:
|
||||
pass
|
||||
if fn in known_malicious_list:
|
||||
return "Virus"
|
||||
return "Safe"
|
||||
return "Unknown"
|
||||
except Exception as e:
|
||||
return f"Error: {e}"
|
||||
|
||||
info = pe_scan("path to file")
|
||||
print(info)
|
||||
```
|
||||
|
||||
## 進程監控
|
||||
|
||||
顯示新進程名稱、檔案路徑、cmd 行、pid
|
||||
```
|
||||
import psutil, time
|
||||
|
||||
def proc_detect():
|
||||
existing_process = set()
|
||||
for p in psutil.process_iter():
|
||||
existing_process.add(p.pid)
|
||||
while True:
|
||||
time.sleep(0.1)
|
||||
new_process = set()
|
||||
for p in psutil.process_iter():
|
||||
new_process.add(p.pid)
|
||||
for pid in new_process - existing_process:
|
||||
try:
|
||||
p = psutil.Process(pid)
|
||||
name, file, cmd = p.name(), p.exe(), p.cmdline()
|
||||
print(f"Name: {name}")
|
||||
print(f"File: {file}")
|
||||
print(f"Pid: {p.pid}")
|
||||
print(f"Cmd: {cmd}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
existing_process = new_process
|
||||
|
||||
proc_detect()
|
||||
```
|
||||
|
||||
## 檔案監控
|
||||
|
||||
監控指定路徑下的檔案變化
|
||||
```
|
||||
import os, win32file, win32con
|
||||
|
||||
def file_detect(path):
|
||||
hDir = win32file.CreateFile(path,win32con.GENERIC_READ,win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE|win32con.FILE_SHARE_DELETE,None,win32con.OPEN_EXISTING,win32con.FILE_FLAG_BACKUP_SEMANTICS,None)
|
||||
while True:
|
||||
for action, file in win32file.ReadDirectoryChangesW(hDir,10485760,True,win32con.FILE_NOTIFY_CHANGE_FILE_NAME|win32con.FILE_NOTIFY_CHANGE_DIR_NAME|win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES|win32con.FILE_NOTIFY_CHANGE_SIZE|win32con.FILE_NOTIFY_CHANGE_LAST_WRITE|win32con.FILE_NOTIFY_CHANGE_SECURITY,None,None):
|
||||
try:
|
||||
fpath = os.path.join(path, file)
|
||||
if action == 1:
|
||||
print(f"File Create: {fpath}")
|
||||
elif action == 2:
|
||||
print(f"File Delete: {fpath}")
|
||||
elif action == 3:
|
||||
print(f"File Modify: {fpath}")
|
||||
elif action == 4:
|
||||
print(f"File Rename: {fpath}")
|
||||
elif action == 5:
|
||||
print(f"File Rename: {fpath}")
|
||||
except:
|
||||
pass
|
||||
|
||||
file_detect("path")
|
||||
```
|
||||
|
||||
## 官方網頁
|
||||
|
||||
https://pyantivirus.wixsite.com/pyas
|
||||
|
||||
https://github.com/87owo/PYAS
|
||||
|
||||
## 開源協議
|
||||
|
||||
https://github.com/87owo/PYAS/blob/main/LICENSE.md
|
||||
|
||||
## 驅動程式
|
||||
|
||||
https://github.com/0sha0/PYAS_Protection
|
||||
|
||||
## 支援系統
|
||||
|
||||
Windows 8.1, 10, 11 (64-bit),記憶體 500MB, 磁碟容量 200MB 或更高
|
||||
|
||||
其他系統或版本可能會遇到軟體功能故障或程序崩潰
|
||||
|
||||
## 特別感謝
|
||||
|
||||
Wix, 0sha0, mtkiao129, AV-T Team of LisectGroup
|
||||
|
||||
Copyright© 2020~2024 PYAS Security By 87owo
|
||||
Reference in new issue
Block a user