This detection identifies adversaries who have deployed obfuscated ASP webshells utilizing the ASPEncodeDLL tool to conceal malicious code from static analysis and evade signature-based defenses. Proactive hunting for this behavior in Azure Sentinel is critical because encoded webshells often bypass standard monitoring, allowing attackers to establish persistent command-and-control channels that can lead to data exfiltration or lateral movement if left undetected.
rule WEBSHELL_ASP_Encoded_AspCoding
{
meta:
description = "ASP Webshell encoded using ASPEncodeDLL.AspCoding"
license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE"
author = "Arnim Rupp (https://github.com/ruppde)"
reference = "Internal Research"
date = "2021/03/14"
modified = "2023-07-05"
score = 60
hash = "7cfd184ab099c4d60b13457140493b49c8ba61ee"
hash = "f5095345ee085318235c11ae5869ae564d636a5342868d0935de7582ba3c7d7a"
id = "788a8dae-bcb8-547c-ba17-e1f14bc28f34"
strings:
$encoded1 = "ASPEncodeDLL" fullword nocase wide ascii
$encoded2 = ".Runt" nocase wide ascii
$encoded3 = "Request" fullword nocase wide ascii
$encoded4 = "Response" fullword nocase wide ascii
$data1 = "AspCoding.EnCode" wide ascii
//$sus1 = "shell" nocase wide ascii
//$sus2 = "cmd" fullword wide ascii
//$sus3 = "password" fullword wide ascii
//$sus4 = "UserPass" fullword wide ascii
//strings from private rule capa_asp
$tagasp_short1 = /<%[^"]/ wide ascii
// also looking for %> to reduce fp (yeah, short atom but seldom since special chars)
$tagasp_short2 = "%>" wide ascii
// classids for scripting host etc
$tagasp_classid1 = "72C24DD5-D70A-438B-8A42-98424B88AFB8" nocase wide ascii
$tagasp_classid2 = "F935DC22-1CF0-11D0-ADB9-00C04FD58A0B" nocase wide ascii
$tagasp_classid3 = "093FF999-1EA0-4079-9525-9614C3504B74" nocase wide ascii
$tagasp_classid4 = "F935DC26-1CF0-11D0-ADB9-00C04FD58A0B" nocase wide ascii
$tagasp_classid5 = "0D43FE01-F093-11CF-8940-00A0C9054228" nocase wide ascii
$tagasp_long10 = "<%@ " wide ascii
// <% eval
$tagasp_long11 = /<% \w/ nocase wide ascii
$tagasp_long12 = "<%ex" nocase wide ascii
$tagasp_long13 = "<%ev" nocase wide ascii
// <%@ LANGUAGE = VBScript.encode%>
// <%@ Language = "JScript" %>
// <%@ WebHandler Language="C#" class="Handler" %>
// <%@ WebService Language="C#" Class="Service" %>
// <%@Page Language="Jscript"%>
// <%@ Page Language = Jscript %>
// <%@PAGE LANGUAGE=JSCRIPT%>
// <%@ Page Language="Jscript" validateRequest="false" %>
// <%@ Page Language = Jscript %>
// <%@ Page Language="C#" %>
// <%@ Page Language="VB" ContentType="text/html" validaterequest="false" AspCompat="true" Debug="true" %>
// <script runat="server" language="JScript">
// <SCRIPT RUNAT=SERVER LANGUAGE=JSCRIPT>
// <SCRIPT RUNAT=SERVER LANGUAGE=JSCRIPT>
// <msxsl:script language="JScript" ...
$tagasp_long20 = /<(%|script|msxsl:script).{0,60}language="?(vb|jscript|c#)/ nocase wide ascii
$tagasp_long32 = /<script\s{1,30}runat=/ wide ascii
$tagasp_long33 = /<SCRIPT\s{1,30}RUNAT=/ wide ascii
// avoid hitting php
$php1 = "<?php"
$php2 = "<?="
// avoid hitting jsp
$jsp1 = "=\"java." wide ascii
$jsp2 = "=\"javax." wide ascii
$jsp3 = "java.lang." wide ascii
$jsp4 = "public" fullword wide ascii
$jsp5 = "throws" fullword wide ascii
$jsp6 = "getValue" fullword wide ascii
$jsp7 = "getBytes" fullword wide ascii
$perl1 = "PerlScript" fullword
condition:
filesize < 500KB and (
(
any of ( $tagasp_long* ) or
// TODO : yara_push_private_rules.py doesn't do private rules in private rules yet
any of ( $tagasp_classid* ) or
(
$tagasp_short1 and
$tagasp_short2 in ( filesize-100..filesize )
) or (
$tagasp_short2 and (
$tagasp_short1 in ( 0..1000 ) or
$tagasp_short1 in ( filesize-1000..filesize )
)
)
) and not (
(
any of ( $perl* ) or
$php1 at 0 or
$php2 at 0
) or (
( #jsp1 + #jsp2 + #jsp3 ) > 0 and ( #jsp4 + #jsp5 + #jsp6 + #jsp7 ) > 0
)
)
)
and all of ( $encoded* ) and any of ( $data* )
}
This YARA rule can be deployed in the following contexts:
This rule contains 33 string patterns in its detection logic.
Here are 3-5 specific false positive scenarios for the ASP Webshell encoded using ASPEncodeDLL.AspCoding detection rule, including suggested filters and exclusions:
Scenario: Scheduled Backup of Legacy Intranet Portals
C:\InetPub\wwwroot\LegacyHR directory. This directory contains older ASP pages protected by ASPEncodeDLL to prevent source code theft. When the backup service reads these encoded .asp files, the file signature triggers the webshell detection logic due to the specific encoding pattern of the DLL.vrb.exe, robocopy.exe) and the Source Directory Path. Exclude alerts where the process is running under a dedicated service account (e.g., DOMAIN\svc_backup) accessing paths containing \LegacyHR\.Scenario: Automated Deployment via Azure DevOps Release Pipeline
SYSTEM or DOMAIN\devops_agent) extracts and writes encoded ASP files generated by the build process. The detection rule interprets the writing of these pre-encoded files as a potential new webshell creation event.msbuild.exe, devenv.exe, or the specific Azure DevOps agent executable (Microsoft.VisualStudio.Services.Agent.Worker.Service). Additionally, exclude events occurring during defined maintenance windows (e.g., 02:00–04:00 UTC) on