Xiao-Ping Zhang

44 papers B 1Journal 38Unranked 5
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE Access
Mohamed S. Alashqar, Xiao-Ping Zhang, Ahmed M. Massoud, Guolong Ma
2025 J jnl
IEEE Access
Shami Ahmad Assery, Nan Chen, Xiao-Ping Zhang
2024 J jnl
IEEE Access
Yinru Chen, Xiao-Ping Zhang, Shuhao Yan
2024 J jnl
IEEE Trans. Smart Grid
Qirun Sun, Zhi Wu, Wei Gu, Xiao-Ping Zhang, Yuping Lu, Pengxiang Liu, Shuai Lu, Haifeng Qiu
2023 conf
ISGT EUROPE
Junyi Zhai, Xinliang Dai, Yuning Jiang, Ying Xue, Veit Hagenmeyer, Colin N. Jones, Xiao-Ping Zhang
2023 J jnl
IEEE Trans. Smart Grid
Suhan Zhang, Wei Gu, Xiao-Ping Zhang, Hai Lu, Ruizhi Yu, Haifeng Qiu, Shuai Lu
2023 J jnl
IEEE Trans. Smart Grid
Guolong Ma, Jianing Li, Xiao-Ping Zhang
2022 J jnl
IEEE Access
Guolong Ma, Jianing Li, Xiao-Ping Zhang
2022 J jnl
IEEE Access
Yixin Li, Xiao-Ping Zhang, Ning Li
2022 J jnl
IEEE Trans. Veh. Technol.
Ning Li, Fuxing He, Wentao Ma, Ruotong Wang, Lin Jiang, Xiao-Ping Zhang
2022 J jnl
IEEE Trans. Smart Grid
Junyi Zhai, Yuning Jiang, Yuanming Shi, Colin N. Jones, Xiao-Ping Zhang
2022 J jnl
IEEE Access
Mahmoud M. Elgamasy, Mohamed A. Izzularab, Xiao-Ping Zhang
2022 J jnl
Sensors
Ning Li, Longhui Zhu, Wentao Ma, Yelin Wang, Fuxing He, Aixiang Zheng, Xiao-Ping Zhang
2022 J jnl
Sensors
Ning Li, Fuxing He, Wentao Ma, Ruotong Wang, Lin Jiang, Xiao-Ping Zhang
2021 J jnl
IEEE Trans. Smart Grid
Yujian Ye, Yi Tang, Huiyu Wang, Xiao-Ping Zhang, Goran Strbac
2021 J jnl
IEEE Access
Cong Wu, Xiao-Ping Zhang, Michael J. H. Sterling
2021 J jnl
IEEE Access
Xianxian Zhao, Ying Xue, Xiao-Ping Zhang
2021 J jnl
IEEE Access
Conghuan Yang, Ying Xue, Xiao-Ping Zhang
2020 J jnl
Entropy
Chenyixuan Ni, Xiaodai Xue, Shengwei Mei, Xiao-Ping Zhang, Xiaotao Chen
2020 J jnl
IEEE Access
Ning Li, Fuxing He, Wentao Ma, Ruotong Wang, Xiao-Ping Zhang
2019 J jnl
IEEE Access
Zhou Li, Yazhou Li, Ruopei Zhan, Yan He, Xiao-Ping Zhang
2019 J jnl
IEEE Access
Fayou Yan, Puyu Wang, Xiao-Ping Zhang, Jufang Xie, Xiaodong Li, Chao Tang, Zhongyong Zhao
2019 J jnl
IEEE Access
Puyu Wang, Na Deng, Xiao-Ping Zhang, Ningqiang Jiang
2019 J jnl
IEEE Access
Kanghui Gu, Feng Wu, Xiao-Ping Zhang, Ping Ju, Haiqiang Zhou, Jiajie Luo, Jianing Li
2019 J jnl
IEEE Access
Jiajie Luo, Xiao-Ping Zhang, Ying Xue
2019 B conf
SMC
Min Zhao, Hang Yin, Ying Xue, Xiao-Ping Zhang
2018 J jnl
IEEE Access
Zhi Wu, Xiao Du, Wei Gu, Xiao-Ping Zhang, Junjie Li
2018 J jnl
IEEE Access
Conghuan Yang, Ying Xue, Xiao-Ping Zhang, Yi Zhang, Yuan Chen
2017 J jnl
IEEE Access
Zuanhong Yan, Xiao-Ping Zhang
2017 J jnl
IEEE Access
Hao Fu, Xiao-Ping Zhang
2017 J jnl
IEEE Access
Xianxian Zhao, Zuanhong Yan, Ying Xue, Xiao-Ping Zhang
2016 J jnl
IEEE Access
Xianxian Zhao, Zuanhong Yan, Xiao-Ping Zhang
2014 J jnl
IEEE Trans. Smart Grid
Pengwei Du, Ning Lu, Jianhui Wang, Xiao-Ping Zhang, Ralph Masiello, Mike Henderson
2014 J jnl
IEEE Trans. Smart Grid
Carlos Suazo-Martinez, Eduardo Pereira-Bonvallet, Rodrigo Palma-Behnke, Xiao-Ping Zhang
2014 conf
PSCC
Peter Pingliang Zeng, Zhi Wu, Xiao-Ping Zhang, Caihao Liang, Yantao Zhang
2014 J jnl
IEEE Trans. Smart Grid
Zhi Wu, Suyang Zhou, Jianing Li, Xiao-Ping Zhang
2013 conf
ISGT Europe
Na Deng, Xiao-Ping Zhang, Puyu Wang, Xinxin Gu, Ming Wu
2013 J jnl
IEEE Trans. Smart Grid
Xiao-Ping Zhang, Ronnie Belmans, Daniel S. Kirschen, David Sun, Ebrahim Vaahedi, Yusheng Xue
2013 J jnl
Proc. IEEE
Xiao-Ping Zhang, Pingliang Zeng
2013 J jnl
Proc. IEEE
Feng Wu, Ping Ju, Xiao-Ping Zhang, Chuan Qin, Guo-Jing Peng, Hua Huang, Jing Fang
2012 conf
ISGT Europe
Suyang Zhou, Xiao-Ping Zhang, Xuan Yang
2012 J jnl
Proc. IEEE
Xiao-Ping Zhang
2012 J jnl
IEEE Trans. Smart Grid
Gan Li, Xiao-Ping Zhang
2007 conf
SoSE
Xiao-Ping Zhang, C.-F. Xue, Keith R. Godfrey
redb/extractors/js_extractors/js_deobfuscator.py
← Index redb/extractors/js_extractors/js_deobfuscator.py python
"""Subprocess-driven JavaScript deobfuscator with jsbeautifier fallback.

Owns the heavy lifting that was previously embedded inside
`JSDeobfuscationExtractor` (`_run_deobfuscator` + `_try_jsbeautifier`). Exposed
as a single module-level entry point `deobfuscate(source, log)` so it can be
called from `JSContext.deobfuscated` (cached per sample) without dragging
extractor state through the call.

Configuration (env vars):
    JS_DEOBFUSCATOR_PATH    Path or name of the external tool (default: webcrack).
    JS_DEOBFUSCATE_TIMEOUT  Seconds before the external tool is killed
                            (process-group SIGTERM, then SIGKILL). Default: 60.

If the external tool produces non-empty output and exits 0, that wins. Otherwise
the source is run through jsbeautifier (which only normalises formatting, but
already exposes strings hidden by minification). If neither path produces
output, returns (None, None).

`FileNotFoundError` for the external tool is treated as routine — the analysis
server is either provisioned with the tool or it isn't — and demoted to a
debug-level log.
"""

import os
import signal
import subprocess
import tempfile
from typing import Optional, Tuple

DEFAULT_DEOBFUSCATOR = "webcrack"
DEFAULT_TIMEOUT_SECS = 60


def _run_external(
    source: str, deobfuscator_path: str, timeout: int, log
) -> Tuple[Optional[str], int]:
    """Run the configured external deobfuscator over `source` and capture stdout.

    Returns (text, returncode). `text` is `None` and `returncode` is `-1` when
    the binary is missing, the run timed out, or any other unexpected failure
    occurred. Missing-binary is logged at debug; timeouts and unexpected errors
    surface at warning/error.
    """
    try:
        with tempfile.NamedTemporaryFile(
            suffix=".js", mode="w", delete=False, encoding="utf-8"
        ) as tmp:
            tmp.write(source)
            tmp_path = tmp.name

        try:
            process = subprocess.Popen(
                [deobfuscator_path, tmp_path],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                preexec_fn=os.setsid,
            )

            try:
                stdout, _ = process.communicate(timeout=timeout)
                return stdout.decode("utf-8", errors="replace"), process.returncode
            except subprocess.TimeoutExpired:
                # Kill the entire process group so spawned helpers (e.g. node
                # subprocesses webcrack itself launches) get cleaned up too.
                try:
                    os.killpg(os.getpgid(process.pid), signal.SIGTERM)
                    process.wait(timeout=5)
                except Exception:
                    try:
                        os.killpg(os.getpgid(process.pid), signal.SIGKILL)
                    except Exception:
                        pass
                log.warning(f"Deobfuscation timed out after {timeout}s")
                return None, -1
        finally:
            try:
                os.unlink(tmp_path)
            except Exception:
                pass
    except FileNotFoundError:
        log.debug(f"Deobfuscator binary not found at {deobfuscator_path}")
        return None, -1
    except Exception as e:
        log.error(f"Error running deobfuscator: {e}")
        return None, -1


def _try_jsbeautifier(source: str, log) -> Tuple[Optional[str], Optional[str]]:
    """Fallback path: format the source with jsbeautifier. Returns
    `(text, "jsbeautifier")` or `(None, None)` if jsbeautifier isn't installed
    or the call raised."""
    try:
        import jsbeautifier
        opts = jsbeautifier.default_options()
        opts.indent_size = 2
        return jsbeautifier.beautify(source, opts), "jsbeautifier"
    except ImportError:
        log.debug("jsbeautifier not available")
        return None, None
    except Exception as e:
        log.warning(f"jsbeautifier failed: {e}")
        return None, None


def deobfuscate(source: str, log) -> Tuple[Optional[str], Optional[str]]:
    """Run the configured external deobfuscator, falling back to jsbeautifier.

    Returns `(text, normalizer_used)` on success, or `(None, None)` when neither
    path produced non-empty output. `normalizer_used` is the basename of the
    external tool (e.g. `"webcrack"`) or the literal `"jsbeautifier"`.
    """
    if not source:
        return None, None

    deobfuscator_path = os.getenv("JS_DEOBFUSCATOR_PATH", DEFAULT_DEOBFUSCATOR)
    timeout = int(os.getenv("JS_DEOBFUSCATE_TIMEOUT", str(DEFAULT_TIMEOUT_SECS)))

    text, returncode = _run_external(source, deobfuscator_path, timeout, log)
    if text and returncode == 0 and text.strip():
        return text, os.path.basename(deobfuscator_path)

    return _try_jsbeautifier(source, log)