File uploads, code releases, and data sharing pipelines can introduce malicious files—ransomware, mining programs, web shells, and more—that threaten your systems and data. The malicious file detection feature is built on the multi-engine detection platform of Security Center and provides multiple methods to identify and handle these risks. This document helps users with different roles quickly select the most appropriate detection method based on their business scenario.
Feature overview
Use cases
Scenario | Description |
Server attack prevention | Prevent worms and mining Trojans to avoid server resource consumption or use in DDoS attacks. |
Targeted attack defense | Detect backdoors and hacking tools to prevent data theft or remote system control. |
Office network and file storage | Identify documents or compressed files with malicious macros or scripts to prevent phishing and credential theft. |
Full system environment detection | Scan for and remove ransomware and infectious viruses to prevent data from being held for ransom or widespread system paralysis. |
Detection methods
Security Center provides two methods to perform detection tasks: SDK integration and console operation.
Feature | SDK integration | Console operation |
How to use | Call the SDK in your business code. Java and Python are supported. | Use the Security Center console to scan buckets through a graphical interface. |
Supported file sources |
| OSS files only. |
Scope
Supported file types
Compressed file detection: Supports decompressing and scanning unencrypted compressed packages. The decompression level and file count are configurable.
Encrypted file detection: Supports automatically decrypting and scanning data encrypted with OSS server-side encryption (SSE-KMS, SSE-OSS).
Supported file formats:
Compressed packages:
.7z,.zip,.rar,.tar,.gz,.bz2,.xz,.lzma,.ar,.tar.gz.Scripts/WebShell:
.php,.jsp,.jspx,.asp,.aspx,.sh,.py,.ps1,.pl,.bat,.html.Documents:
.doc,.pdf,.ppt,.xsl,.rtf,.hta,.chm,.docx.Images:
.jpg,.jpeg,.png.Executables and binaries:
.apk,.exe,.dll,.ocx,.com,.so,.sys,.ko,.obj.
Supported virus types: Supports detecting reverse shell backdoors, DDoS Trojans, mining programs, and other virus files. For more information, see Supported virus types.
Storage class restrictions: Only files stored in OSS with the storage class of Standard or Infrequent Access can be detected. Archive storage class is not supported.
Supported regions for OSS bucket detection:
China (Qingdao), China (Beijing), China (Zhangjiakou), China (Hohhot), China (Ulanqab)
China (Hangzhou), China (Shanghai)
China (Shenzhen), China (Heyuan), China (Guangzhou)
China (Chengdu), China (Hong Kong)
Singapore, Malaysia (Kuala Lumpur), Indonesia (Jakarta), Philippines (Manila), Thailand (Bangkok), Japan (Tokyo), South Korea (Seoul), US (Silicon Valley), US (Virginia), Germany (Frankfurt), UK (London)
Purchase and activate the service
Access the Security Center console - Risk Governance - Malicious File Detection. At the top of the left side of the page, select the region where the asset to be protected is located: Chinese Mainland or Outside Chinese Mainland.
Follow the on-screen instructions to select Try Now,Buy Now (Subscription)or Activate Pay-as-you-go to activate the feature.
Free trial: If your Alibaba Cloud account has passed enterprise real-name verification, you can activate a free trial of malicious file detection.
ImportantEach Alibaba Cloud account is eligible for one free trial only.
The trial provides 10,000 malicious file detections.
Subscription:You are redirected to the purchase page. Configure and complete the purchase based on the following descriptions.
In the Malicious File Detection section, set Purchase or Not to Yes.
Enter the required number of detections (minimum purchase: 100,000). The field is Quantity.
Pay-as-you-go:
In the pay-as-you-go activation dialog, click Activate Pay-as-you-go.
Enable Policy (Optional): Selecting the option enables automatic periodic detection of newly uploaded files in selected buckets. This policy takes effect immediately. To modify the detection scope, go toPolicy configuration.
You can also go to theSecurity Center purchase pagefor more information. For details, see Security Center purchase page.
Configure notifications (optional)
Security Center provides DingTalk robot notifications to automatically push malicious file alert information to DingTalk groups for timely response to detected risks. Follow these steps:
Access the Security Center console - System Settings - Notifications. At the top of the left side of the page, select the region where the asset to be protected is located: Chinese Mainland or Outside Chinese Mainland.
On the DingTalk Chatbot tab, click Add Chatbot.
Notify On: Select all levels for malicious file detection.
Other options: See Configure DingTalk chatbot notifications.
Configure and run detection tasks
Console operation
If the files to be detected are stored in Alibaba Cloud Object Storage OSS buckets, you can perform batch or periodic scans on the target OSS bucket files directly in the Security Center console.
Manual detection: One-time scans of existing files, supporting both full detection and incremental detection.
Automatic detection: Continuous scanning of newly uploaded files based on a policy.
Manual detection (existing files)
Enter the OSS file detection page
Access the Security Center console - Risk Governance - Malicious File Detection. At the top of the left side of the page, select the region where the asset to be protected is located: Chinese Mainland or Outside Chinese Mainland.and open the OSS File Check tab.
Start a detection task
ImportantIf a bucket does not appear in the OSS File Check list, click Synchronize Buckets,to refresh the latest bucket list.
full detection:
Function description: Scan all files in one or more buckets.
Entry:
Single detection: In the target bucket Actions column, click Check.
Batch detection: Select multiple buckets and click Batch detection at the bottom of the list.
Incremental detection
Function description: For buckets that have been detected and have file updates since the last detection, only new or changed files since the last task are detected.
Entry: In the Actions column of the target bucket, click Incremental detection.
Configure detection parameters
In the dialog box that appears, configure the parameters as needed.
File Check Type: Select the file extensions to scan. By default, all file types are detected.
Decompression Level and Max Files per Archive:To scan inside compressed packages, set the decompression level (up to 5 levels) and the maximum file count per package (up to 1,000). By default, decompression is disabled.
File Decryption Type: If OSS files are encrypted with server-side encryption (SSE-OSS or SSE-KMS), select the corresponding decryption method so that Security Center can decrypt and detect them.
Scan Path:
Match by Prefix: Enter a file name prefix to match and scan specific files.
Configure for Entire Bucket: Scan all files in the bucket.
Wait for the detection task to complete
NoteAfter the detection task is complete, the backend needs to perform data statistics and synchronization. Results are typically delayed by 1 to 2 hours . Please wait patiently.
On the bucket list page, view the target File Check Status. When the status changes from Not Checked to Checked, the detection is complete.
Automatic detection (incremental files)
Enter the policy management page
Access the Security Center console - Risk Governance - Malicious File Detection. At the top of the left side of the page, select the region where the asset to be protected is located: Chinese Mainland or Outside Chinese Mainland.
Click Policy Management.
Create or modify a detection policy
Create a new policy: In the Policy Management panel, click Create Policy.
Modify an existing policy: In the Actions column of an existing policy, click Edit to add the target bucket to the policy scope.
After completing the configuration based on the following descriptions, click OK.
Increment Real-time Detection:
NoteOnly Chinese Mainland regions support real-time incremental detection. Outside Chinese Mainland regions do not support this feature.
Enable: Detection is triggered immediately when a new file is uploaded to the specified bucket.
Disable: Scans new files based on the configured detection cycle (e.g., daily, every 3 days) and file detection time window (e.g., 02:00-04:00) within the period.
Effective Bucket:Select one or more buckets to apply this policy to. If a bucket is already occupied by another policy, it cannot be selected again.
WarningAfter a policy takes effect, it does not automatically detect files in newly added buckets. If detection is needed, manually edit the policy to add them to the "Active Bucket" list.
Detection Cycle: Select the detection task execution cycle.
File Check Time: Select the detection task execution time. The interval must be at least 1 hour.
WarningIf a detection task runs beyond the specified detection time, it will be automatically suspended and will automatically restart in the next detection cycle.
Other parameters ((e.g., decompression, decryption, scan path)): See the Configure detection parameters of Manual detection.
SDK integration
Integrate malicious file detection into your business code and retrieve malicious file information from the returned results to detect files.
Step 1: Prepare access credentials and permissions
Create an AccessKey
To ensure account security, do not use the AccessKey of your primary account. We recommend that you create a RAM user dedicated to API access and grant it the minimum necessary permissions. For more information, seeCreate a RAM user,Create an AccessKey.
New account
Log on to the RAM console with your primary account or RAM administrator account. On the Users page, click Create User.
Configure the following:
User Account Information:Enter the user login name, tags, and other information.
Direct Access:Select Using permanent AccessKey to access.
After security verification, the system automatically generates an AccessKey ID and an AccessKey Secret for the RAM user. Keep the credentials safe.
NoteYou can download the credential CSV file or copy the content and save it locally. For more information, see Create an AccessKey.
Existing RAM account
Log on to the RAM console with your primary account or RAM administrator account, and open the details page of the target user.
On the Logon-free Configuration tab, in the AccessKey Pair section, clickCreate an AccessKey.
Select the use case based on your business needs, select I confirm that I must create an AccessKey, and click Continue.
After security verification, the system automatically generates an AccessKey ID and an AccessKey Secret for the RAM user. Keep the credentials safe.
NoteYou can download the credential CSV file or copy the content and save it locally. For more information, see Create an AccessKey.
Configure permission policies
On the Users page, click the target RAM user. In the Actions column, click Grant permissions to the user..
In the Policy section, select AliyunYundunSASFullAccess, and then click Confirm Authorization.
NoteFor more information, see Grant permissions to a RAM user.
Configure environment variables
Alibaba Cloud SDKs support creating default access credentials by defining the
ALIBABA_CLOUD_ACCESS_KEY_IDandALIBABA_CLOUD_ACCESS_KEY_SECRETenvironment variables. When you call an API, the program directly accesses the credentials, reads the access key (AccessKey), and automatically completes authentication. For more information, seeConfigure environment variables.Linux/macOS
Configure the AccessKey ID and press Enter.
# Replace yourAccessKeyID with your AccessKey ID. export ALIBABA_CLOUD_ACCESS_KEY_ID=yourAccessKeyIDConfigure the AccessKey secret and press Enter.
# Replace yourAccessKeySecret with your AccessKey secret. export ALIBABA_CLOUD_ACCESS_KEY_SECRET=yourAccessKeySecretVerify the configuration.
Run the
echo $ALIBABA_CLOUD_ACCESS_KEY_IDcommand. If the command returns the correct AccessKey ID, the configuration is successful.
Windows
Use the graphical user interface (GUI)
Procedure
The following steps describe how to set environment variables using the GUI in Windows 10.
On your desktop, right-click This PC and choose Properties > Advanced system settings > Environment Variables > New under System variables or User variables. Then, complete the configuration.
Variable
Example value
AccessKey ID
Variable name: ALIBABA_CLOUD_ACCESS_KEY_ID
Variable value: yourAccessKeyID
AccessKey Secret
Variable name: ALIBABA_CLOUD_ACCESS_KEY_SECRET
Variable value: yourAccessKeySecret
Test the configuration
Click Start (or use the Win+R keyboard shortcut), click Run, enter `cmd`, and then click OK (or press Enter) to open the command prompt. Run the
echo %ALIBABA_CLOUD_ACCESS_KEY_ID%andecho %ALIBABA_CLOUD_ACCESS_KEY_SECRET%commands. If the commands return the correct AccessKey, the configuration is successful.
Use the command prompt (CMD)
Procedure
Open the command prompt as an administrator and run the following commands to add new environment variables to the system.
setx ALIBABA_CLOUD_ACCESS_KEY_ID yourAccessKeyID /M setx ALIBABA_CLOUD_ACCESS_KEY_SECRET yourAccessKeySecret /MThe
/Mparameter indicates a system environment variable. You can omit this parameter when you set a user environment variable.Test the configuration
Click Start (or use the Win+R keyboard shortcut), click Run, enter `cmd`, and then click OK (or press Enter) to open the command prompt. Run the
echo %ALIBABA_CLOUD_ACCESS_KEY_ID%andecho %ALIBABA_CLOUD_ACCESS_KEY_SECRET%commands. If the commands return the correct AccessKey, the configuration is successful.
Using Windows PowerShell
In PowerShell, you can set new environment variables that are valid for all new sessions:
[System.Environment]::SetEnvironmentVariable('ALIBABA_CLOUD_ACCESS_KEY_ID', 'yourAccessKeyID', [System.EnvironmentVariableTarget]::User) [System.Environment]::SetEnvironmentVariable('ALIBABA_CLOUD_ACCESS_KEY_SECRET', 'yourAccessKeySecret', [System.EnvironmentVariableTarget]::User)To set environment variables for all users, you must have administrative permissions:
[System.Environment]::SetEnvironmentVariable('ALIBABA_CLOUD_ACCESS_KEY_ID', 'yourAccessKeyID', [System.EnvironmentVariableTarget]::Machine) [System.Environment]::SetEnvironmentVariable('ALIBABA_CLOUD_ACCESS_KEY_SECRET', 'yourAccessKeySecret', [System.EnvironmentVariableTarget]::Machine)You can set temporary environment variables that are valid only for the current session:
$env:ALIBABA_CLOUD_ACCESS_KEY_ID = "yourAccessKeyID" $env:ALIBABA_CLOUD_ACCESS_KEY_SECRET = "yourAccessKeySecret"In PowerShell, run the
Get-ChildItem env:ALIBABA_CLOUD_ACCESS_KEY_IDandGet-ChildItem env:ALIBABA_CLOUD_ACCESS_KEY_SECRETcommands. If the commands return the correct AccessKey, the configuration is successful.
Step 2: Install the SDK
Select the installation method based on your development language. Currently, only Java and Python are supported.
Java
Prerequisite:JDK 1.8 or later.
Installation:
Go to theJava SDK repositoryto download the latest version of the Java SDK file.
Add the downloaded SDK file to your project.
Python
Prerequisite:Python 3.6 or later.
Installation:
Online installation: Install quickly using pip.
<BASH> pip install -U alibabacloud_filedetectOffline installation:
In a networked environment, go to the Python SDK repository to download the latest version of the Python SDK.
Upload the downloaded source package to your project environment and decompress it.
Go to the decompressed SDK root directory and run the installation command:
<BASH> # Change to the Python SDK root directory # The directory name may vary by version, e.g., alibabacloud_filedetect-1.0.0 cd alibabacloud_filedetect-x.x.x/ # Install using your Python version python setup.py install
Step 3: Write code and run detection
After the environment is configured, refer to the following Python and Java code examples to write your code.
Replace the path, URL, and MD5 parameters in the sample code with your actual values.
package com.aliyun.filedetect.sample;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import com.aliyun.filedetect.*;
public class Sample {
/**
* Synchronous file detection interface
* @param detector Detector object
* @param path Path of the file to be detected
* @param timeout_ms Set the timeout period in milliseconds
* @param wait_if_queuefull If the detection queue is full, false indicates returning an error immediately without waiting, while true indicates waiting until the queue has space.
* @throws InterruptedException
*/
public static DetectResult detectFileSync(OpenAPIDetector detector, String path, int timeout_ms, boolean wait_if_queuefull) throws InterruptedException {
if (null == detector || null == path) return null;
DetectResult result = null;
while(true) {
result = detector.detectSync(path, timeout_ms);
if (null == result) break;
if (result.error_code != ERR_CODE.ERR_DETECT_QUEUE_FULL) break;
if (!wait_if_queuefull) break;
detector.waitQueueAvailable(-1);
}
return result;
}
/**
* Asynchronous file detection interface
* @param detector Detector object
* @param path Path of the file to be detected
* @param timeout_ms Set the timeout period in milliseconds
* @param wait_if_queuefull If the detection queue is full, false indicates returning an error immediately without waiting, while true indicates waiting until the queue has space.
* @param callback Callback function for the result
* @throws InterruptedException
*/
public static int detectFile(OpenAPIDetector detector, String path, int timeout_ms, boolean wait_if_queuefull, IDetectResultCallback callback) throws InterruptedException {
if (null == detector || null == path || null == callback) return ERR_CODE.ERR_INIT.value();
int result = ERR_CODE.ERR_INIT.value();
if (wait_if_queuefull) {
final IDetectResultCallback real_callback = callback;
callback = new IDetectResultCallback() {
public void onScanResult(int seq, String file_path, DetectResult callback_res) {
if (callback_res.error_code == ERR_CODE.ERR_DETECT_QUEUE_FULL) return;
real_callback.onScanResult(seq, file_path, callback_res);
}
};
}
while(true) {
result = detector.detect(path, timeout_ms, callback);
if (result != ERR_CODE.ERR_DETECT_QUEUE_FULL.value()) break;
if (!wait_if_queuefull) break;
detector.waitQueueAvailable(-1);
}
return result;
}
/**
* Synchronous URL file detection interface
* @param detector Detector object
* @param url URL of the file to be detected
* @param md5 MD5 hash of the file to be detected
* @param timeout_ms Set the timeout period in milliseconds
* @param wait_if_queuefull If the detection queue is full, false indicates returning an error immediately without waiting, while true indicates waiting until the queue has space.
* @throws InterruptedException
*/
public static DetectResult detectUrlSync(OpenAPIDetector detector, String url, String md5, int timeout_ms, boolean wait_if_queuefull) throws InterruptedException {
if (null == detector || null == url || null == md5) return null;
DetectResult result = null;
while(true) {
result = detector.detectUrlSync(url, md5, timeout_ms);
if (null == result) break;
if (result.error_code != ERR_CODE.ERR_DETECT_QUEUE_FULL) break;
if (!wait_if_queuefull) break;
detector.waitQueueAvailable(-1);
}
return result;
}
/**
* Asynchronous URL file detection interface
* @param detector Detector object
* @param url URL of the file to be detected
* @param md5 MD5 hash of the file to be detected
* @param timeout_ms Set the timeout period in milliseconds
* @param wait_if_queuefull If the detection queue is full, false indicates returning an error immediately without waiting, while true indicates waiting until the queue has space.
* @param callback Callback function for the result
* @throws InterruptedException
*/
public static int detectUrl(OpenAPIDetector detector, String url, String md5, int timeout_ms, boolean wait_if_queuefull, IDetectResultCallback callback) throws InterruptedException {
if (null == detector || null == url || null == md5 || null == callback) return ERR_CODE.ERR_INIT.value();
int result = ERR_CODE.ERR_INIT.value();
if (wait_if_queuefull) {
final IDetectResultCallback real_callback = callback;
callback = new IDetectResultCallback() {
public void onScanResult(int seq, String file_path, DetectResult callback_res) {
if (callback_res.error_code == ERR_CODE.ERR_DETECT_QUEUE_FULL) return;
real_callback.onScanResult(seq, file_path, callback_res);
}
};
}
while(true) {
result = detector.detectUrl(url, md5, timeout_ms, callback);
if (result != ERR_CODE.ERR_DETECT_QUEUE_FULL.value()) break;
if (!wait_if_queuefull) break;
detector.waitQueueAvailable(-1);
}
return result;
}
/**
* Format the detection result
* @param result Detection result object
* @return Formatted string
*/
public static String formatDetectResult(DetectResult result) {
if (result.isSucc()) {
DetectResult.DetectResultInfo info = result.getDetectResultInfo();
String msg = String.format("[DETECT RESULT] [SUCCEED] %s", formatDetectResultInfo(info));
if (info.compresslist != null) {
int idx = 1;
for (DetectResult.CompressFileDetectResultInfo comp_res : info.compresslist) {
msg += String.format("\n\t\t\t [COMPRESS FILE] [IDX:%d] %s", idx++, formatCompressFileDetectResultInfo(comp_res));
}
}
return msg;
}
DetectResult.ErrorInfo info = result.getErrorInfo();
return String.format("[DETECT RESULT] [FAIL] md5: %s, time: %d, error_code: %s, error_message: %s"
, info.md5, info.time, info.error_code.name(), info.error_string);
}
private static String formatDetectResultInfo(DetectResult.DetectResultInfo info) {
String msg = String.format("MD5: %s, TIME: %d, RESULT: %s, SCORE: %d", info.md5, info.time, info.result.name(), info.score);
if (info.compresslist != null) {
msg += String.format(", COMPRESS_FILES: %d", info.compresslist.size());
}
DetectResult.VirusInfo vinfo = info.getVirusInfo();
if (vinfo != null) {
msg += String.format(", VIRUS_TYPE: %s, EXT_INFO: %s", vinfo.virus_type, vinfo.ext_info);
}
return msg;
}
private static String formatCompressFileDetectResultInfo(DetectResult.CompressFileDetectResultInfo info) {
String msg = String.format("PATH: %s, \t\t RESULT: %s, SCORE: %d", info.path, info.result.name(), info.score);
DetectResult.VirusInfo vinfo = info.getVirusInfo();
if (vinfo != null) {
msg += String.format(", VIRUS_TYPE: %s, EXT_INFO: %s", vinfo.virus_type, vinfo.ext_info);
}
return msg;
}
/**
* Synchronously detect a directory or file
* @param path The specified path can be a file or a directory. If it is a directory, its content is recursively traversed.
* @param is_sync Specifies whether to use the synchronous interface. We recommend using the asynchronous interface. true: synchronous, false: asynchronous
* @throws InterruptedException
*/
public static void detectDirOrFileSync(OpenAPIDetector detector, String path, int timeout_ms, Map<String, DetectResult> result_map) throws InterruptedException {
File file = new File(path);
String abs_path = file.getAbsolutePath();
if (file.isDirectory()) {
String[] ss = file.list();
if (ss == null) return;
for (String s : ss) {
String subpath = abs_path + File.separator + s;
detectDirOrFileSync(detector, subpath, timeout_ms, result_map);
}
return;
}
System.out.println(String.format("[detectFileSync] [BEGIN] queueSize: %d, path: %s, timeout: %d", detector.getQueueSize(), abs_path, timeout_ms));
DetectResult res = detectFileSync(detector, abs_path, timeout_ms, true);
System.err.println(String.format(" [ END ] %s", formatDetectResult(res)));
result_map.put(abs_path, res);
}
/**
* Asynchronously detect a directory or file
* @param path The specified path can be a file or a directory. If it is a directory, its content is recursively traversed.
* @param is_sync Specifies whether to use the synchronous interface. We recommend using the asynchronous interface. true: synchronous, false: asynchronous
* @throws InterruptedException
*/
public static void detectDirOrFile(OpenAPIDetector detector, String path, int timeout_ms, IDetectResultCallback callback) throws InterruptedException {
File file = new File(path);
String abs_path = file.getAbsolutePath();
if (file.isDirectory()) {
String[] ss = file.list();
if (ss == null) return;
for (String s : ss) {
String subpath = abs_path + File.separator + s;
detectDirOrFile(detector, subpath, timeout_ms, callback);
}
return;
}
int seq = detectFile(detector, abs_path, timeout_ms, true, callback);
System.out.println(String.format("[detectFile] [BEGIN] seq: %d, queueSize: %d, path: %s, timeout: %d", seq, detector.getQueueSize(), abs_path, timeout_ms));
}
/**
* Start detecting a file or directory
* @param path The specified path can be a file or a directory. If it is a directory, its content is recursively traversed.
* @param is_sync Specifies whether to use the synchronous interface. We recommend using the asynchronous interface. true: synchronous, false: asynchronous
* @throws InterruptedException
*/
public static void scan(final OpenAPIDetector detector, String path, int detect_timeout_ms, boolean is_sync) throws InterruptedException {
System.out.println(String.format("[SCAN] [START] path: %s, detect_timeout_ms: %d, is_sync: %b", path, detect_timeout_ms, is_sync));
long start_time = System.currentTimeMillis();
final Map<String, DetectResult> result_map = new HashMap<>();
if (is_sync) {
detectDirOrFileSync(detector, path, detect_timeout_ms, result_map);
} else {
detectDirOrFile(detector, path, detect_timeout_ms, new IDetectResultCallback() {
public void onScanResult(int seq, String file_path, DetectResult callback_res) {
System.err.println(String.format("[detectFile] [ END ] seq: %d, queueSize: %d, %s", seq, detector.getQueueSize(), formatDetectResult(callback_res)));
result_map.put(file_path, callback_res);
}
});
// Wait for the task to complete.
detector.waitQueueEmpty(-1);
}
long used_time = System.currentTimeMillis() - start_time;
System.out.println(String.format("[SCAN] [ END ] used_time: %d, files: %d", used_time, result_map.size()));
int fail_count = 0;
int white_count = 0;
int black_count = 0;
for (Map.Entry<String, DetectResult> entry : result_map.entrySet()) {
DetectResult res = entry.getValue();
if (res.isSucc()) {
if (res.getDetectResultInfo().result == DetectResult.RESULT.RES_BLACK) {
black_count ++;
} else {
white_count ++;
}
} else {
fail_count ++;
}
}
System.out.println(String.format(" fail_count: %d, white_count: %d, black_count: %d"
, fail_count, white_count, black_count));
}
public static void main(String[] args_) throws Exception {
// Get the detector instance.
OpenAPIDetector detector = OpenAPIDetector.getInstance();
// Initialize.
ERR_CODE init_ret = detector.init(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
System.out.println("INIT RET: " + init_ret.name());
// Set decompression parameters (optional, compressed packages are not decompressed by default).
boolean decompress = true; // Specifies whether to identify and decompress compressed files. Default is false.
int decompressMaxLayer = 5; // Maximum decompression level. Effective when decompress is true.
int decompressMaxFileCount = 1000; // Maximum number of decompressed files. Effective when decompress is true.
ERR_CODE initdec_ret = detector.initDecompress(decompress, decompressMaxLayer, decompressMaxFileCount);
System.out.println("INIT_DECOMPRESS RET: " + initdec_ret.name());
if (true) {
// Example 1: Scan a local directory or file.
boolean is_sync_scan = false; // Specifies whether to use asynchronous or synchronous detection. Asynchronous detection offers better performance. false indicates asynchronous detection.
int timeout_ms = 500000; // Detection time for a single sample, in milliseconds.
String path = "test2.php"; // The file or directory to be scanned.
// Start the scan and wait for it to finish.
scan(detector, path, timeout_ms, is_sync_scan);
}
if (true) {
// Example 2: Scan a URL file.
int timeout_ms = 500000; // Detection time for a single sample, in milliseconds.
String url = "https://xxxxxxxx.oss-cn-hangzhou-1.aliyuncs.com/xxxxx/xxxxxxxxxxxxxx?Expires=1*****25&OSSAccessKeyId=xxx"; // The URL file to be scanned.
String md5 = "a767f*************6e21d000000"; // The MD5 hash of the file to be scanned.
// Synchronous scan. To perform an asynchronous scan, call the detectUrl interface.
System.out.println(String.format("[detectUrlSync] [BEGIN] URL: %s, MD5: %s, TIMEOUT: %d", url, md5, timeout_ms));
DetectResult result = detectUrlSync(detector, url, md5, timeout_ms, true);
System.err.println(String.format("[detectUrlSync] [ END ] %s", formatDetectResult(result)));
}
// Deinitialize.
System.out.println("Over.");
detector.uninit();
}
}
# -*- coding: utf-8 -*-
import os
import sys
from typing import List
import threading
import time
import traceback
from alibabacloud_filedetect.OpenAPIDetector import OpenAPIDetector
from alibabacloud_filedetect.IDetectResultCallback import IDetectResultCallback
from alibabacloud_filedetect.ERR_CODE import ERR_CODE
from alibabacloud_filedetect.DetectResult import DetectResult
class Sample(object):
def __init__(self):
pass
"""
Synchronous file detection interface
@param detector: Detector object
@param path: Path of the file to be detected
@param timeout_ms: Set the timeout period in milliseconds
@param wait_if_queuefull: If the detection queue is full, False indicates returning an error immediately without waiting, while True indicates waiting until the queue has space.
"""
def detectFileSync(self, detector, path, timeout_ms, wait_if_queuefull):
if detector is None or path is None:
return None
result = None
while True:
result = detector.detectSync(path, timeout_ms)
if result is None:
break
if result.error_code != ERR_CODE.ERR_DETECT_QUEUE_FULL:
break
if wait_if_queuefull is False:
break
detector.waitQueueAvailable(-1)
return result
"""
Asynchronous file detection interface
@param detector: Detector object
@param path: Path of the file to be detected
@param timeout_ms: Set the timeout period in milliseconds
@param wait_if_queuefull: If the detection queue is full, False indicates returning an error immediately without waiting, while True indicates waiting until the queue has space.
@param callback: Callback function for the result
"""
def detectFile(self, detector, path, timeout_ms, wait_if_queuefull, callback):
if detector is None or path is None or callback is None:
return ERR_CODE.ERR_INIT.value
result = ERR_CODE.ERR_INIT.value
if wait_if_queuefull:
real_callback = callback
class AsyncTaskCallback(IDetectResultCallback):
def onScanResult(self, seq, file_path, callback_res):
if callback_res.error_code == ERR_CODE.ERR_DETECT_QUEUE_FULL:
return
real_callback.onScanResult(seq, file_path, callback_res)
callback = AsyncTaskCallback()
while True:
result = detector.detect(path, timeout_ms, callback)
if result != ERR_CODE.ERR_DETECT_QUEUE_FULL.value:
break
if wait_if_queuefull is False:
break
detector.waitQueueAvailable(-1)
return result
"""
Synchronous URL file detection interface
@param detector: Detector object
@param url: URL of the file to be detected
@param md5: MD5 hash of the file to be detected
@param timeout_ms: Set the timeout period in milliseconds
@param wait_if_queuefull: If the detection queue is full, False indicates returning an error immediately without waiting, while True indicates waiting until the queue has space.
"""
def detectUrlSync(self, detector, url, md5, timeout_ms, wait_if_queuefull):
if detector is None or url is None or md5 is None:
return None
result = None
while True:
result = detector.detectUrlSync(url, md5, timeout_ms)
if result is None:
break
if result.error_code != ERR_CODE.ERR_DETECT_QUEUE_FULL:
break
if wait_if_queuefull is False:
break
detector.waitQueueAvailable(-1)
return result
"""
Asynchronous URL file detection interface
@param detector: Detector object
@param url: URL of the file to be detected
@param md5: MD5 hash of the file to be detected
@param timeout_ms: Set the timeout period in milliseconds
@param wait_if_queuefull: If the detection queue is full, False indicates returning an error immediately without waiting, while True indicates waiting until the queue has space.
@param callback: Callback function for the result
"""
def detectUrl(self, detector, url, md5, timeout_ms, wait_if_queuefull, callback):
if detector is None or url is None or md5 is None or callback is None:
return ERR_CODE.ERR_INIT.value
result = ERR_CODE.ERR_INIT.value
if wait_if_queuefull:
real_callback = callback
class AsyncTaskCallback(IDetectResultCallback):
def onScanResult(self, seq, file_path, callback_res):
if callback_res.error_code == ERR_CODE.ERR_DETECT_QUEUE_FULL:
return
real_callback.onScanResult(seq, file_path, callback_res)
callback = AsyncTaskCallback()
while True:
result = detector.detectUrl(url, md5, timeout_ms, callback)
if result != ERR_CODE.ERR_DETECT_QUEUE_FULL.value:
break
if wait_if_queuefull is False:
break
detector.waitQueueAvailable(-1)
return result
"""
Format the detection result
@param result: Detection result object
@return: Formatted string
"""
@staticmethod
def formatDetectResult(result):
msg = ""
if result.isSucc():
info = result.getDetectResultInfo()
msg = "[DETECT RESULT] [SUCCEED] {}".format(Sample.formatDetectResultInfo(info))
if info.compresslist is not None:
idx = 1
for comp_res in info.compresslist:
msg += "\n\t\t\t [COMPRESS FILE] [IDX:{}] {}".format(idx, Sample.formatCompressFileDetectResultInfo(comp_res))
idx += 1
else:
info = result.getErrorInfo()
msg = "[DETECT RESULT] [FAIL] md5: {}, time: {}, error_code: {}, error_message: {}".format(info.md5,
info.time, info.error_code.name, info.error_string)
return msg
@staticmethod
def formatDetectResultInfo(info):
msg = "MD5: {}, TIME: {}, RESULT: {}, SCORE: {}".format(info.md5, info.time, info.result.name, info.score)
if info.compresslist is not None:
msg += ", COMPRESS_FILES: {}".format(len(info.compresslist))
vinfo = info.getVirusInfo()
if vinfo is not None:
msg += ", VIRUS_TYPE: {}, EXT_INFO: {}".format(vinfo.virus_type, vinfo.ext_info)
return msg
@staticmethod
def formatCompressFileDetectResultInfo(info):
msg = "PATH: {}, \t\t RESULT: {}, SCORE: {}".format(info.path, info.result.name, info.score)
vinfo = info.getVirusInfo()
if vinfo is not None:
msg += ", VIRUS_TYPE: {}, EXT_INFO: {}".format(vinfo.virus_type, vinfo.ext_info)
return msg
"""
Synchronously detect a directory or file
@param path: The specified path can be a file or a directory. If it is a directory, its content is recursively traversed.
@param is_sync: Specifies whether to use the synchronous interface. We recommend using the asynchronous interface. True: synchronous, False: asynchronous
"""
def detectDirOrFileSync(self, detector, path, timeout_ms, result_map):
abs_path = os.path.abspath(path)
if os.path.isdir(abs_path):
sub_files = os.listdir(abs_path)
if len(sub_files) == 0:
return
for sub_file in sub_files:
sub_path = os.path.join(abs_path, sub_file)
self.detectDirOrFileSync(detector, sub_path, timeout_ms, result_map)
return
print("[detectFileSync] [BEGIN] queueSize: {}, path: {}, timeout: {}".format(
detector.getQueueSize(), abs_path, timeout_ms))
res = self.detectFileSync(detector, abs_path, timeout_ms, True)
print(" [ END ] {}".format(Sample.formatDetectResult(res)))
result_map[abs_path] = res
return
"""
Asynchronously detect a directory or file
@param path: The specified path can be a file or a directory. If it is a directory, its content is recursively traversed.
@param is_sync: Specifies whether to use the synchronous interface. We recommend using the asynchronous interface. True: synchronous, False: asynchronous
"""
def detectDirOrFile(self, detector, path, timeout_ms, callback):
abs_path = os.path.abspath(path)
if os.path.isdir(abs_path):
sub_files = os.listdir(abs_path)
if len(sub_files) == 0:
return
for sub_file in sub_files:
sub_path = os.path.join(abs_path, sub_file)
self.detectDirOrFile(detector, sub_path, timeout_ms, callback)
return
seq = self.detectFile(detector, abs_path, timeout_ms, True, callback)
print("[detectFile] [BEGIN] seq: {}, queueSize: {}, path: {}, timeout: {}".format(
seq, detector.getQueueSize(), abs_path, timeout_ms))
return
"""
Start detecting a file or directory
@param path: The specified path can be a file or a directory. If it is a directory, its content is recursively traversed.
@param is_sync: Specifies whether to use the synchronous interface. We recommend using the asynchronous interface. True: synchronous, False: asynchronous
"""
def scan(self, detector, path, detect_timeout_ms, is_sync):
try:
print("[SCAN] [START] path: {}, detect_timeout_ms: {}, is_sync: {}".format(path, detect_timeout_ms, is_sync))
start_time = time.time()
result_map = {}
if is_sync:
self.detectDirOrFileSync(detector, path, detect_timeout_ms, result_map)
else:
class AsyncTaskCallback(IDetectResultCallback):
def onScanResult(self, seq, file_path, callback_res):
print("[detectFile] [ END ] seq: {}, queueSize: {}, {}".format(seq,
detector.getQueueSize(), Sample.formatDetectResult(callback_res)))
result_map[file_path] = callback_res
self.detectDirOrFile(detector, path, detect_timeout_ms, AsyncTaskCallback())
# Wait for the task to complete.
detector.waitQueueEmpty(-1)
used_time_ms = (time.time() - start_time) * 1000
print("[SCAN] [ END ] used_time: {}, files: {}".format(int(used_time_ms), len(result_map)))
failed_count = 0
white_count = 0
black_count = 0
for file_path, res in result_map.items():
if res.isSucc():
if res.getDetectResultInfo().result == DetectResult.RESULT.RES_BLACK:
black_count += 1
else:
white_count += 1
else:
failed_count += 1
print(" fail_count: {}, white_count: {}, black_count: {}".format(
failed_count, white_count, black_count))
except Exception as e:
print(traceback.format_exc(), file=sys.stderr)
def main(self):
# Get the detector instance.
detector = OpenAPIDetector.get_instance()
# Read the AccessKey ID and AccessKey Secret from environment variables.
access_key_id = os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID')
access_key_secret = os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET')
# Initialize.
init_ret = detector.init(access_key_id, access_key_secret)
print("INIT RET: {}".format(init_ret.name))
# Set decompression parameters (optional, compressed packages are not decompressed by default).
decompress = True # Specifies whether to identify and decompress compressed files. Default is false.
decompressMaxLayer = 5 # Maximum decompression level. Effective when decompress is true.
decompressMaxFileCount = 1000 # Maximum number of decompressed files. Effective when decompress is true.
initdec_ret = detector.initDecompress(decompress, decompressMaxLayer, decompressMaxFileCount)
print("INIT_DECOMPRESS RET: {}".format(initdec_ret.name))
if True:
# Example 1: Scan a local directory or file.
is_sync_scan = False # Specifies whether to use asynchronous or synchronous detection. Asynchronous detection offers better performance. False indicates asynchronous detection.
timeout_ms = 500000 # Detection time for a single sample, in milliseconds.
path = "test.bin" # The file or directory to be scanned.
# Start the scan and wait for it to finish.
self.scan(detector, path, timeout_ms, is_sync_scan)
if True:
# Example 2: Scan a URL file.
timeout_ms = 500000
url = "https://xxxxxxxx.oss-cn-hangzhou-1.aliyuncs.com/xxxxx/xxxxxxxxxxxxxx?Expires=1671448125&OSSAccessKeyId=xxx" # The URL file to be scanned.
md5 = "a767ffc59d93125c7505b6e21d000000"
# Synchronous scan. To perform an asynchronous scan, call the detectUrl interface.
print("[detectUrlSync] [BEGIN] URL: {}, MD5: {}, TIMEOUT: {}".format(url, md5, timeout_ms))
result = self.detectUrlSync(detector, url, md5, timeout_ms, True)
print("[detectUrlSync] [ END ] {}".format(Sample.formatDetectResult(result)))
# Deinitialize.
print("Over.")
detector.uninit()
if __name__ == "__main__":
sample = Sample()
sample.main()
Step 4: Parse the returned results
After you call the SDK to detect malicious files, you can view the detection results in the program output. The results are also synced to the Security Center console.
Result data structure: Each detection returns a
DetectResultobject. The core fields are as follows:Field
Type
Description
md5String
The MD5 hash value of the file.
timelong
The time used for this detection (in milliseconds).
error_codeERR_CODE
Error code.
ERR_SUCCindicates success.error_stringString
Detailed error information.
resultRESULT (enum)
Detection result enum:
RES_WHITE:SafeRES_BLACK:Suspicious/MaliciousRES_PENDING:Pending.
scoreint
Detection score. Range: 0-100. A higher score indicates a higher risk.
0 ~ 60: Safe, The file is trusted and usually requires no action.
61 ~ 70: Risk (Low), The file has a minor risk. Manual review is recommended.
71 ~ 80: Suspicious (Medium), the file is likely malicious. Isolation or deletion is recommended.
81 ~ 100: Malicious (High), the file is almost certainly malicious. Isolate or delete it immediately.
virus_typeString
Virus type, such as WebShell, MalScript, Hacktool, etc.
ext_infoString
Extended information, usually a JSON string containing more detailed detection context.
compresslistList
If the detected file is a compressed file and decompression is enabled, this list contains the detection results of each file in the compressed package.
Error codes and troubleshooting
Error code
Description
Cause
Suggested solution
ERR_SUCCSuccess
Detection completed successfully.
None
ERR_INITInitialization error
The SDK needs to be initialized, or was initialized repeatedly.
Ensure that
init()has been called successfully before calling the detection interface.ERR_FILE_NOT_FOUNDFile not found
The specified local file path does not exist.
Check whether the file path is correct and whether the program has file read permissions.
ERR_CALL_APIAPI call error
An unknown error occurred when calling the cloud API.
Check the code and parameter values.
ERR_TIMEOUTTimeout
The detection time exceeded the configured
timeout_ms.Increase
timeout_msparameter value, or check the network connection.ERR_UPLOADUpload failed
The file failed to upload to the cloud for analysis. You can retry.
Usually a network issue. We recommend adding retry logic.
ERR_ABORTTask aborted
The program exited before detection was completed. The detection file count may have exceeded the pre-paid quota, or the account balance is insufficient for pay-as-you-go billing.
Purchase additional detection counts or recharge your account.
ERR_DETECT_QUEUE_FULLDetection queue full
Detection tasks were submitted too frequently and the server-side queue is full.
This may occur during peak hours. You can call
waitQueueAvailable()to wait for the queue to become available, or retry later.ERR_TIMEOUT_QUEUEQueue timeout
The wait time in the queue was too long.
ERR_MD5MD5 format error
The provided MD5 string format is incorrect.
Correct the MD5 format.
ERR_URLURL format error
The provided URL string format is incorrect.
Correct the URL format.
View and process detection results
View results
At-risk File Overview tab:
Centrally displays all risk files detected by all detection methods (OSS detection and API calls). You can search, filter risk files, and view their risk levels, threat tags, and other information.
For compressed files, click the expand
icon before the file to view the list of risk files in the package.
OSS File Check tab:
Displays risk statistics by bucket, such as the number of risk files and detection progress for each bucket.
Click the Actions column of an existing policy, and click Details to view the associated malicious file list.
Result delivery: If you have enabled Security Center Log Analysis or Log Management features, malicious file detection logs will be automatically stored in a dedicated Logstore in Security Center for deep queries and traceability analysis. For more information, see SAS log delivery and SIEM logs.
Process results:Supports operations on detection results including Add to Whitelist,Ignore,Denied Access and other operations. For specific operations, see Handle malicious file detection results.
Quotas and limits
Purchase restrictions: Each Alibaba Cloud account can select only one billing method at a time.
NoteSwitching billing methods does not affect the display of existing detection results or the execution of periodic policies.
File size limits:
Total file size per task: No limit.
Single file size limit:
SDK offline file detection: single file must not exceed 100 MB.
Console OSS file detection: single file must not exceed 1 GB.
Over-limit description:
When the file size exceeds the limit or the decompressed files exceed the quantity/size limit, the relevant files will not be detected. Undetected files are not counted toward the billing count.
When malicious file detection requests exceed the queue capacity, you need to wait, or optimize the concurrency processing capability.
Compressed file detection limits: Up to 5 decompression levels, 1,000 files, and 1 GB total size.
Environment restrictions: Financial Cloud and Government Cloud environments are not supported.
Default API request rate (QPS): Trial: 10 requests/second. Paid: 20 requests/second.
NoteDetection speed is affected by network conditions, server performance, cloud product specifications, and other factors.
The SDK uses an asynchronous queue mechanism to handle request peaks and improve concurrency. When the internal queue is full, new requests are paused until the queue has available space.
Troubleshooting
Bucket list is empty or target bucket not found
Cause: The bucket region is not within the supported regions for malicious file detection.
Solution: Confirm whether the bucket region is in theScopelist of supported regions. If not supported, copy the files to a bucket in a supported region.
Cause: The bucket list has not been synced.
Solution:On the OSS File Check tab, click Synchronize Buckets to sync the latest bucket list.
Insufficient permissions or authorization failure
Cause:The Security Center service-linked role has not been created, or the permission policy is incomplete.
Solution: Ensure that the current Alibaba Cloud account has RAM management permissions. When you activate malicious file detection for the first time, the system automatically creates the service-linked role
AliyunServiceRoleForSasFileDetect.To create it manually, seeCreate a RAM user.
Detection task cannot be initiated or insufficient quota
Cause:The Subscription resource pack has expired, or the Pay-as-you-go account balance is insufficient.
Solution:Go to the Security Center Overview page to view the current available detection count. If the count is insufficient, seeSecurity Center purchase pageto renew or recharge.
Cause: The detection queue is full, exceeding the QPS limit.
Solution:The default QPS is 10 requests/second for the trial version and 20 requests/second for the paid version. Reduce the concurrency frequency or retry later.
Encrypted files cannot be detected
Cause:The OSS file uses an unsupported encryption method, or the decryption method is incorrectly selected.
Solution:Malicious file detection only supports OSS server-side encryption (SSE-KMS, SSE-OSS). Select the File Decryption Type.Client-side encryption or third-party encrypted files are not supported.
Billing description
The malicious file detection feature is billed based on the number of detected files, calculated as file detection count.
Billing method:Supports Free trial, Subscription (prepaid), and Pay-as-you-go (postpaid).
Free trial:Alibaba Cloud accounts with enterprise real-name verification can use the free trial, which provides 10,000 detection counts.
ImportantIf the free trial counts are not fully used, after activating the paid version, the remaining free trial counts can continue to be used and are deducted first.
Subscription: The resource pack unit price is USD 1.5 per 10,000 detections per month. Minimum purchase: 100,000 detections. The quota is valid within the selected validity period and expires after that.
Pay-as-you-go:
File detection count is billed on a natural day basis. The unit price is USD 0.0002 per detection.
After activating the Pay-as-you-go service, the system will charge for the Security Center Billing description( USD 0.0072 per hour).
Compressed file billing:If compressed file detection is enabled, the detection counts consumed are calculated based on the number of decompressed files.
Example: Detecting a compressed package containing 1,000 small files consumes 1,000 detection counts.
Process detection results: Included in the feature service fee. No additional charge.
For more information about billing models and logic, seeBilling description.
Unsubscribe from the service
Subscription
On the Security Center console - Overview page Subscription section, click .
On the Order Downgrade tab, in the Malicious File Detection section, set Purchase or Not to No, and then click Order Now.
Pay-as-you-go
Method 1: On the Security Center console - Overviewpage Enable Pay-as-You-Go Service section, disable the Malicious File Detection switch.
Method 2:
Access the Security Center console - Risk Governance - Malicious File Detection. At the top of the left side of the page, select the region where the asset to be protected is located: Chinese Mainland or Outside Chinese Mainland.
On the At-risk File Overview tab, click Used Quotas in the Suspended.
FAQ
Billing and quota
Can used file detection counts be refunded?
No. Before detection, confirm the file scope and detection policy to avoid wasting detection counts due to misoperation.
Why are "Total Files" and "Detected Total Files" inconsistent on the OSS file detection tab?
Total Files: The natural number of files in the bucket (a compressed package counts as 1 ).
Detected Total Files: The actual number of files scanned. If compressed file scanning is enabled, the internal files are also counted. The total number depends on the Decompression Level and maximum decompressed file count settings. This value is the cumulative total of files across all historical detection tasks in the current bucket, not the number of files scanned in a single detection task. Even if a file has been deleted, its historical detection record is still counted, so Detected Total Files may be larger than the current Total Files in the bucket.
When a compressed package with a large number of files is scanned, "Detected Total Files" will be much larger than "Total Files". Billing is based on the actual number of detected files.
What should I do if the detection task is interrupted due to insufficient quota?
If you use the Subscription model, the scan task will be interrupted when the remaining detection counts are insufficient. Refer to the following solutions:
Cancel the current scan task: On the OSS File Check page, find the bucket that is being scanned, and click Cancel Detection in the Actions column to cancel the scan task in progress.
Upgrade configuration:Access the Security Center console - Overview page Subscription section, click Change Configuration>Upgrade Now to purchase sufficient malicious file detection counts. For more information, see Upgrade or downgrade.
Modify detection policy:Disable compressed file decompression in the detection settings to reduce the count consumed per task, and then rerun the scan.
If you do not cancel the current task and directly renew and continue scanning, the system still decompresses and scans the files inside compressed packages, which keeps consuming your detection counts.
Authorization management
How do I view the authorization details of the malicious file SDK (such as remaining count and expiration time)?
You can view the Personal SDK Authorization of the current account in the console, including version, activation status, authorization limits, remaining count, rate limits, and expiration time.
Access the Security Center console - Risk Governance - Malicious File Detection. At the top of the left side of the page, select the region where the asset to be protected is located: Chinese Mainland or Outside Chinese Mainland.
Click SDK and Permissions.
What should I do if I receive a prompt "Malicious file detection SDK purchased but not yet used" or "Notification not configured"?
Purchased but not yet used:This means detection quota has been purchased but no detection task has been executed. Refer to the "Configure and run detection tasks" section in this topic to perform manual detection via the console or integrate the SDK to initiate detection.
Notification not configured:This means detection result notifications have not been configured, which does not affect the detection feature itself. To receive notifications when malicious files are detected, refer to the "Configure notifications (optional)" section in this topic to complete the setup. Once configured, the prompt will disappear.
Appendix
API reference
You can use the malicious file detection feature by calling API operations. Some reference documents are listed below.
Supported virus types
Virus type (virus_type) | Virus name |
Backdoor | Reverse shell backdoor |
DDoS | DDoS Trojan |
Downloader | Downloader Trojan |
Engtest | Engine test program |
Hacktool | Hacking tool |
Trojan | High-risk program |
Malbaseware | Contaminated base software |
MalScript | Malicious script |
Malware | Malware |
Miner | Mining program |
Proxytool | Proxy tool |
RansomWare | Ransomware |
RiskWare | Riskware |
Rootkit | Rootkit |
Stealer | Stealer |
Scanner | Scanner |
Suspicious | Suspicious program |
Virus | Infectious virus |
WebShell | Web shell |
Worm | Worm |
AdWare | Adware |
Patcher | Patcher |
Gametool | Game tool |