EXPLORE
← Back to Explore
elastichighTTP

WPS Office Exploitation via DLL Hijack

Identifies the load of a remote library by the WPS Office promecefpluginhost.exe executable. This may indicate the successful exploitation of CVE-2024-7262 or CVE-2024-7263 via DLL hijack abusing the ksoqing custom protocol handler.

MITRE ATT&CK

executioninitial-accessdefense-evasion

Detection Query

any where host.os.type == "windows" and process.name : "promecefpluginhost.exe" and
(
 (event.category == "library" and
  ?dll.path :
     ("?:\\Users\\*\\AppData\\Local\\Temp\\wps\\INetCache\\*",
      "\\Device\\Mup\\**", "\\\\*")) or

  ((event.category == "process" and event.action : "Image loaded*") and
  ?file.path :
     ("?:\\Users\\*\\AppData\\Local\\Temp\\wps\\INetCache\\*",
      "\\Device\\Mup\\**", "\\\\*"))
)

Author

Elastic

Created

2024/08/29

Data Sources

Elastic DefendSysmonlogs-endpoint.events.library-*logs-windows.sysmon_operational-*

Tags

Domain: EndpointOS: WindowsUse Case: Threat DetectionTactic: Initial AccessTactic: ExecutionData Source: Elastic DefendData Source: SysmonResources: Investigation Guide
Raw Content
[metadata]
creation_date = "2024/08/29"
integration = ["endpoint", "windows"]
maturity = "production"
updated_date = "2026/05/01"

[rule]
author = ["Elastic"]
description = """
Identifies the load of a remote library by the WPS Office promecefpluginhost.exe executable. This may indicate the
successful exploitation of CVE-2024-7262 or CVE-2024-7263 via DLL hijack abusing the ksoqing custom protocol handler.
"""
from = "now-9m"
index = ["logs-endpoint.events.library-*", "logs-windows.sysmon_operational-*"]
language = "eql"
license = "Elastic License v2"
name = "WPS Office Exploitation via DLL Hijack"
references = [
    "https://www.welivesecurity.com/en/eset-research/analysis-of-two-arbitrary-code-execution-vulnerabilities-affecting-wps-office/",
    "https://mp.weixin.qq.com/s/F8hNyESBdKhwXkQPgtGpew",
]
risk_score = 73
rule_id = "ac6bc744-e82b-41ad-b58d-90654fa4ebfb"
severity = "high"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Initial Access",
    "Tactic: Execution",
    "Data Source: Elastic Defend",
    "Data Source: Sysmon",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
any where host.os.type == "windows" and process.name : "promecefpluginhost.exe" and
(
 (event.category == "library" and
  ?dll.path :
     ("?:\\Users\\*\\AppData\\Local\\Temp\\wps\\INetCache\\*",
      "\\Device\\Mup\\**", "\\\\*")) or

  ((event.category == "process" and event.action : "Image loaded*") and
  ?file.path :
     ("?:\\Users\\*\\AppData\\Local\\Temp\\wps\\INetCache\\*",
      "\\Device\\Mup\\**", "\\\\*"))
)
'''

note = """## Triage and analysis

### Investigating WPS Office Exploitation via DLL Hijack

#### Possible investigation steps

- What WPS library-load path did the alert capture?
  - Why: WPS loading from cache, device, or UNC paths defines the likely abuse route before identity checks.
  - Focus: `process.name`, `process.executable`, `process.command_line`, `dll.path`, and `dll.name`.
  - Implication: escalate when "promecefpluginhost.exe" loads from "Temp\\wps\\INetCache", "\\Device\\Mup\\", or a UNC path outside the WPS install tree; lower suspicion only when normalized `dll.path` resolves to the same Kingsoft-controlled component path as the loader and no protocol-abuse arguments appear.

- Is the WPS loader the expected Kingsoft component?
  - Focus: `process.executable`, `process.pe.original_file_name`, `process.hash.sha256`, `process.code_signature.subject_name`, and `process.code_signature.trusted`.
  - Implication: escalate when the loader is unsigned, renamed, outside the installed WPS Office directory, or signed by an unexpected publisher; lower suspicion when identity matches a stable Kingsoft WPS component, but continue because a trusted loader can still load an attacker DLL.

- Does the command line and parentage show "ksoqing" protocol abuse?
  - Focus: loader process events for `host.id` and `process.entity_id`, then `process.command_line`, `process.parent.executable`, and `process.parent.command_line`. $investigate_2
  - Implication: escalate when "wps.exe" or "et.exe" opens user content with arguments exposing "ksoqing", plugin-service paths, encoded paths, or remote paths; lower suspicion only when parentage and arguments match a recognized controlled-share launch without document-driven protocol handling.

- Does the loaded DLL identity fit a legitimate WPS dependency?
  - Focus: `dll.hash.sha256`, `dll.pe.original_file_name`, `dll.code_signature.subject_name`, `dll.code_signature.trusted`, and `dll.Ext.relative_file_creation_time`.
  - Hint: if endpoint file telemetry is available, use `host.id` and `dll.path` to identify the writer or rename event. Missing file telemetry is unresolved, not benign. $investigate_4
  - Implication: escalate when the DLL is unsigned, non-Kingsoft, recently created, recently renamed in `dll.Ext.relative_file_name_modify_time`, or loaded as an unexpected WPS dependency from a remote share; if recency metadata is absent, rely on path, hash, signer, and parentage.

- If local evidence is suspicious or incomplete, do related alerts show follow-on activity?
  - Focus: child process events from the WPS loader and related alerts for `user.id`, especially WPS document execution, additional library loads, downloader behavior, or child-process alerts from the same workstation.
    - $investigate_3
    - $investigate_0
  - Hint: if user context is missing or ambiguous, review same-host alerts for `host.id` across the last 48 hours. $investigate_1
  - Implication: broaden scope when the same user or host shows repeated WPS-triggered loads, the same `dll.hash.sha256`, the same suspicious path pattern, or follow-on execution; lower urgency when isolated, but do not close if local path or DLL identity remains unresolved.

- Escalate when load path, loader identity, protocol or parentage, DLL signer/hash/recency, or related-alert evidence supports attacker-controlled DLL loading from INetCache, a device path, or UNC path; close only when the same evidence binds to one authorized validation, sandbox, or controlled-share workflow with no contradictory artifacts; preserve artifacts and escalate if evidence is mixed or incomplete.

### False positive analysis

- Authorized vulnerability validation or sandbox detonation can reproduce this load pattern. Confirm scope with outside records when available, and require telemetry alignment on `host.id`, `user.id`, `process.executable`, `process.command_line`, `dll.path`, `dll.hash.sha256`, and `dll.code_signature.subject_name`. If not a known test, default to suspicious.
- Controlled software distribution or application virtualization can serve WPS components from a managed share. Confirm `dll.path` stays on that exact share, `dll.hash.sha256` and `dll.code_signature.subject_name` match the expected Kingsoft component, and parentage lacks document-driven protocol or plugin-path arguments. Without inventories, use recurrence only to validate the same stable share, hash, signer, `process.executable`, `host.id`, and `user.id` workflow before exceptioning.
- Build exceptions only from the minimum confirmed workflow: stable `process.executable`, `process.code_signature.subject_name`, `dll.path`, `dll.hash.sha256`, `dll.code_signature.subject_name`, and bounded `host.id` or `user.id` scope. Avoid exceptions on `process.name` alone for "promecefpluginhost.exe", "Temp\\wps\\INetCache", or UNC prefixes.

### Response and remediation

- If confirmed benign, record the exact workflow evidence first: loader identity, `process.command_line`, DLL path/hash/signer, and bounded `host.id` or `user.id` scope. Then reverse temporary containment and create an exception only for that bounded workflow.
- If suspicious but unconfirmed, preserve the alert, host/user scope, `process.entity_id`, parent lineage, `dll.path`, `dll.hash.sha256`, and DLL signer/recency evidence before containment. Use reversible actions first, such as restricting a non-business remote share named in `dll.path`, quarantining a recovered lure document, or temporarily restricting WPS on the affected host; isolate only when follow-on execution or repeated malicious loads justify the interruption.
- If confirmed malicious, isolate the host through endpoint response after evidence preservation, then terminate the WPS loader chain if it is still active and block confirmed malicious `dll.hash.sha256` values and remote shares from `dll.path`. If endpoint response is unavailable, hand off the preserved process, DLL, host, and user identifiers to the team that can contain the system or share.
- Eradicate only artifacts tied to the investigation: remove the malicious DLL, recovered lure document, and staged WPS abuse files after scope review for the same `dll.hash.sha256`, `dll.path`, WPS parentage, `host.id`, and `user.id`. Upgrade WPS Office to a vendor-supported release that remediates both CVE-2024-7262 and CVE-2024-7263.
- Post-incident hardening: restrict WPS Office library loads from user-writable and UNC paths where feasible, retain process and library-load telemetry, and document any adjacent variant observed during triage, such as alternate WPS protocol arguments or related "promecefpluginhost.exe" load paths.
"""

setup = """## Setup

This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.

Setup instructions: https://ela.st/install-elastic-defend

### Additional data sources

This rule also supports the following third-party data sources. For setup instructions, refer to the links below:

- [Sysmon Event ID 7 - Image Loaded](https://ela.st/sysmon-event-7-setup)
"""

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "host.name",
    "host.id",
    "user.id",
    "process.executable",
    "process.command_line",
    "process.entity_id",
    "process.code_signature.subject_name",
    "process.code_signature.trusted",
    "process.parent.executable",
    "process.parent.command_line",
    "dll.path",
    "dll.hash.sha256",
    "dll.code_signature.subject_name",
    "dll.code_signature.trusted",
]

[transform]

[[transform.investigate]]
label = "Alerts associated with the user"
description = ""
providers = [
  [
    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
    { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }
  ]
]
relativeFrom = "now-48h/h"
relativeTo = "now"

[[transform.investigate]]
label = "Alerts associated with the host"
description = ""
providers = [
  [
    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
  ]
]
relativeFrom = "now-48h/h"
relativeTo = "now"

[[transform.investigate]]
label = "Process events for the WPS loader"
description = ""
providers = [
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
  ]
]
relativeFrom = "now-1h"
relativeTo = "now"

[[transform.investigate]]
label = "Child process events from the WPS loader"
description = ""
providers = [
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.parent.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
  ]
]
relativeFrom = "now-1h"
relativeTo = "now"

[[transform.investigate]]
label = "File events for the loaded DLL path"
description = ""
providers = [
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "file.path", queryType = "phrase", value = "{{dll.path}}", valueType = "string" }
  ]
]
relativeFrom = "now-1h"
relativeTo = "now"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1129"
name = "Shared Modules"
reference = "https://attack.mitre.org/techniques/T1129/"

[[rule.threat.technique]]
id = "T1203"
name = "Exploitation for Client Execution"
reference = "https://attack.mitre.org/techniques/T1203/"

[rule.threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1189"
name = "Drive-by Compromise"
reference = "https://attack.mitre.org/techniques/T1189/"

[rule.threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1574"
name = "Hijack Execution Flow"
reference = "https://attack.mitre.org/techniques/T1574/"

[[rule.threat.technique.subtechnique]]
id = "T1574.001"
name = "DLL"
reference = "https://attack.mitre.org/techniques/T1574/001/"

[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"