Mahsa Derakhshani

84 papers B 17C 1Journal 44Unranked 21
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE J. Sel. Areas Commun.
Halvin Yang, Sangarapillai Lambotharan, Mahsa Derakhshani
2026 J jnl
Biomed. Signal Process. Control.
Xiaoyu Zheng, Sijung Hu, Vincent M. Dwyer, Laura A. Barrett, Mahsa Derakhshani
2026 J jnl
IEEE Commun. Mag.
Halvin Yang, Sangarapillai Lambotharan, Mahsa Derakhshani, Lajos Hanzo
2026 J jnl
IEEE Wirel. Commun. Lett.
Shenhong Li, Juan Zhu, Tao Feng, Mahsa Derakhshani
2026 J jnl
IEEE J. Sel. Areas Commun.
Halvin Yang, Mahsa Derakhshani, Sangarapillai Lambotharan, Lajos Hanzo
2025 conf
WD
Aobakwe John Makgarapa, Sangarapillai Lambotharan, Mahsa Derakhshani
2025 J jnl
IEEE Access
Lincoln Kamau Kiarie, Mahsa Derakhshani, Konstantinos G. Kyriakopoulos
2025 J jnl
IEEE Internet Things Mag.
Mahsa Derakhshani, Marco Di Renzo, M. Majid Butt, Cunhua Pan, Sanjeewa Herath, Saeedeh Parsaeefard
2025 J jnl
CoRR
Xiaoyu Zheng, Sijung Hu, Vincent M. Dwyer, Mahsa Derakhshani, Laura A. Barrett
2025 conf
VTC2025-Fall
Wenqing Li, Yasaman Omid, Bo Ai, Yong Niu, Mahsa Derakhshani
2025 J jnl
IEEE Trans. Commun.
Yasaman Omid, Marios Aristodemou, Sangarapillai Lambotharan, Mahsa Derakhshani, Lajos Hanzo
2024 B conf
PIMRC
Shenhong Li, Mahsa Derakhshani, Chung Shue Chen, Jun Zhang, Sangarapillai Lambotharan
2024 J jnl
IEEE Trans. Wirel. Commun.
Wenheng Zhang, Mahsa Derakhshani, Gan Zheng, Sangarapillai Lambotharan
2023 J jnl
IEEE Trans. Wirel. Commun.
Wenheng Zhang, Mahsa Derakhshani, Gan Zheng, Chung Shue Chen, Sangarapillai Lambotharan
2023 J jnl
IEEE J. Biomed. Health Informatics
Xiaoyu Zheng, Vincent M. Dwyer, Laura A. Barrett, Mahsa Derakhshani, Sijung Hu
2023 J jnl
IEEE J. Sel. Areas Commun.
Xingchi Liu, Mahsa Derakhshani, Lyudmila Mihaylova, Sangarapillai Lambotharan
2023 conf
ISWCS
Yasaman Omid, Sangarapillai Lambotharan, Mahsa Derakhshani
2022 J jnl
Biomed. Signal Process. Control.
Xiaoyu Zheng, Vincent M. Dwyer, Laura A. Barrett, Mahsa Derakhshani, Sijung Hu
2022 conf
VTC Spring
Wenheng Zhang, Mahsa Derakhshani, Saeed R. Khosravirad, Sangarapillai Lambotharan
2022 C conf
HealthCom
Xiaoyu Zheng, Mahsa Derakhshani, Laura A. Barrett, Vincent M. Dwyer, Sijung Hu
2022 J jnl
IEEE Trans. Veh. Technol.
Mohammad Robat Mili, Shenhong Li, Fatemeh Mokhtari, Mahsa Derakhshani, Farid Ashtiani, Tho Le-Ngoc
2021 J jnl
IEEE Trans. Commun.
Xingchi Liu, Mahsa Derakhshani, Sangarapillai Lambotharan
2021 conf
ICT
Zhan Wang, Mahsa Derakhshani, Robert M. Edwards
2021 conf
ICAIIC
Xingchi Liu, Mahsa Derakhshani, Ziming Zhu, Sangarapillai Lambotharan
2021 conf
ICC
Wenheng Zhang, Mahsa Derakhshani, Sangarapillai Lambotharan
2021 J jnl
IEEE Signal Process. Lett.
Xingchi Liu, Mahsa Derakhshani, Sangarapillai Lambotharan, Mihaela van der Schaar
2021 J jnl
IEEE Wirel. Commun. Lett.
Wenheng Zhang, Mahsa Derakhshani, Sangarapillai Lambotharan
2021 J jnl
IEEE Trans. Cloud Comput.
Saeedeh Parsaeefard, Vikas Jumba, Atoosa Dalili Shoaei, Mahsa Derakhshani, Tho Le-Ngoc
2020 J jnl
IEEE Commun. Lett.
Maryam Mohsenivatani, Ye Liu, Mahsa Derakhshani, Saeedeh Parsaeefard, Sangarapillai Lambotharan
2020 J jnl
IEEE Trans. Commun.
Shenhong Li, Mahsa Derakhshani, Sangarapillai Lambotharan, Lajos Hanzo
2019 J jnl
IEEE Access
Atoosa Dalili Shoaei, Mahsa Derakhshani, Tho Le-Ngoc
2019 conf
ICC
Atoosa Dalili Shoaei, Mahsa Derakhshani, Tho Le-Ngoc
2019 J jnl
IEEE Trans. Commun.
Mina Baghani, Saeedeh Parsaeefard, Mahsa Derakhshani, Walid Saad
2019 J jnl
IEEE Commun. Lett.
Xingchi Liu, Mahsa Derakhshani, Sangarapillai Lambotharan
2019 B conf
GLOBECOM
Shenhong Li, Mahsa Derakhshani, Chung Shue Chen, Sangarapillai Lambotharan
2019 J jnl
IEEE Trans. Commun.
Atoosa Dalili Shoaei, Mahsa Derakhshani, Tho Le-Ngoc
2019 J jnl
IEEE Access
Mahsa Derakhshani, Yahya Khan, Duc Tuong Nguyen, Saeedeh Parsaeefard, Atoosa Dalili Shoaei, Tho Le-Ngoc
2018 J jnl
IEEE Access
Mahsa Derakhshani, Xiaowei Wang, Daniel Tweed, Tho Le-Ngoc, Alberto Leon-Garcia
2018 J jnl
IEEE Trans. Commun.
Ye Liu, Mahsa Derakhshani, Saeedeh Parsaeefard, Sangarapillai Lambotharan, Kai-Kit Wong
2018 J jnl
IEEE Trans. Commun.
Atoosa Dalili Shoaei, Mahsa Derakhshani, Tho Le-Ngoc
2018 J jnl
IET Networks
Mahsa Derakhshani, Saeedeh Parsaeefard, Tho Le-Ngoc, Alberto Leon-Garcia
2018 J jnl
IEEE Commun. Lett.
Ye Liu, Mahsa Derakhshani, Sangarapillai Lambotharan
2018 conf
ICC
Shenhong Li, Mahsa Derakhshani, Sangarapillai Lambotharan
2018 J jnl
IEEE Trans. Commun.
Ye Liu, Sangarapillai Lambotharan, Mahsa Derakhshani, Arumugam Nallanathan, Kai-Kit Wong
2017 B conf
GLOBECOM
Ye Liu, Mahsa Derakhshani, Sangarapillai Lambotharan
2017 J jnl
IEEE Trans. Veh. Technol.
Saeedeh Parsaeefard, Rajesh Dawadi, Mahsa Derakhshani, Tho Le-Ngoc, Mina Baghani
2017 B conf
PIMRC
Daniel Tweed, Saeedeh Parsaeefard, Mahsa Derakhshani, Tho Le-Ngoc
2017 B conf
GLOBECOM
Atoosa Dalili Shoaei, Mahsa Derakhshani, Tho Le-Ngoc, Mohamed Salem
2017 J jnl
IEEE Access
Daniel Tweed, Mahsa Derakhshani, Saeedeh Parsaeefard, Tho Le-Ngoc
2017 conf
NOF
Sara Shakeri, Saeedeh Parsaeefard, Mahsa Derakhshani
2016 B conf
WCNC
Rajesh Dawadi, Saeedeh Parsaeefard, Mahsa Derakhshani, Tho Le-Ngoc
2016 conf
WCNC Workshops
Saeedeh Parsaeefard, Vikas Jumba, Mahsa Derakhshani, Tho Le-Ngoc
2016 B conf
WCNC
Saeedeh Parsaeefard, Vikas Jumba, Mahsa Derakhshani, Tho Le-Ngoc
2016 conf
VTC Fall
Atoosa Dalili Shoaei, Mahsa Derakhshani, Saeedeh Parsaeefard, Tho Le-Ngoc
2016 J jnl
IEEE Access
Saeedeh Parsaeefard, Rajesh Dawadi, Mahsa Derakhshani, Tho Le-Ngoc
2016 J jnl
CoRR
Mahsa Derakhshani, Saeedeh Parsaeefard, Tho Le-Ngoc, Alberto Leon-Garcia
2016 J jnl
IEEE Trans. Veh. Technol.
Atoosa Dalili Shoaei, Mahsa Derakhshani, Saeedeh Parsaeefard, Tho Le-Ngoc
2016 B conf
GLOBECOM
Rajesh Dawadi, Saeedeh Parsaeefard, Mahsa Derakhshani, Tho Le-Ngoc
2015 conf
GLOBECOM Workshops
Mahsa Derakhshani, Xiaowei Wang, Tho Le-Ngoc, Alberto Leon-Garcia
2015 B conf
PIMRC
Vikas Jumba, Saeedeh Parsaeefard, Mahsa Derakhshani, Tho Le-Ngoc
2015 conf
ICUWB
Rajesh Dawadi, Saeedeh Parsaeefard, Mahsa Derakhshani, Tho Le-Ngoc
2015 conf
ICUWB
Vikas Jumba, Saeedeh Parsaeefard, Mahsa Derakhshani, Tho Le-Ngoc
2015 B conf
PIMRC
Xiaowei Wang, Mahsa Derakhshani, Tho Le-Ngoc
2015 J jnl
CoRR
Saeedeh Parsaeefard, Rajesh Dawadi, Mahsa Derakhshani, Tho Le-Ngoc
2015 B conf
WCNC
Saeedeh Parsaeefard, Vikas Jumba, Mahsa Derakhshani, Tho Le-Ngoc
2015 B conf
PIMRC
Atoosa Dalili Shoaei, Mahsa Derakhshani, Saeedeh Parsaeefard, Tho Le-Ngoc
2015 J jnl
IEEE Wirel. Commun. Lett.
Vikas Jumba, Saeedeh Parsaeefard, Mahsa Derakhshani, Tho Le-Ngoc
2015 conf
GLOBECOM Workshops
Yahya Khan, Mahsa Derakhshani, Saeedeh Parsaeefard, Tho Le-Ngoc
2015 J jnl
CoRR
Mahsa Derakhshani, Xiaowei Wang, Tho Le-Ngoc, Alberto Leon-Garcia
2014 conf
ICC
Quang-Dung Ho, Chon-Wang Chao, Mahsa Derakhshani, Tho Le-Ngoc
2014 book
Mahsa Derakhshani, Tho Le-Ngoc
2014 J jnl
IEEE Trans. Veh. Technol.
Mahsa Derakhshani, Tho Le-Ngoc
2014 B conf
PIMRC
Xiaowei Wang, Mahsa Derakhshani, Tho Le-Ngoc
2013 B conf
GLOBECOM
Mahsa Derakhshani, Tho Le-Ngoc
2012 J jnl
IEEE Trans. Veh. Technol.
Mahsa Derakhshani, Tho Le-Ngoc
2012 B conf
GLOBECOM
Mahsa Derakhshani, Tho Le-Ngoc
2012 J jnl
IEEE Trans. Wirel. Commun.
Mahsa Derakhshani, Tho Le-Ngoc
2012 B conf
WCNC
Mahsa Derakhshani, Tho Le-Ngoc
2012 conf
VTC Fall
Mahsa Derakhshani, Tho Le-Ngoc
2011 B conf
GLOBECOM
Mahsa Derakhshani, Tho Le-Ngoc
2011 conf
CCECE
Mahsa Derakhshani, Tho Le-Ngoc
2011 J jnl
IEEE Trans. Wirel. Commun.
Mahsa Derakhshani, Tho Le-Ngoc, Masoumeh Nasiri-Kenari
2010 conf
VTC Fall
Mahsa Derakhshani, Tho Le-Ngoc
2010 conf
ICC
Mahsa Derakhshani, Masoumeh Nasiri-Kenari, Tho Le-Ngoc
redb/extractors/js_extractors/js_strings.py
← Index redb/extractors/js_extractors/js_strings.py python
import base64
import bisect
import inspect
import re
from datetime import datetime, timezone
from typing import Any

from redb.extractors.enum import Tag
from redb.extractors.js_extractor import JSExtractor
from redb.extractors.js_extractors.js_patterns import STRING_PATTERNS, line_offsets

# Local aliases for the compiled patterns this extractor uses. Defined and
# compiled exactly once in js_patterns.STRING_PATTERNS.
_HEX_STRING_RE = STRING_PATTERNS["hex_escape_seq"]
_UNICODE_STRING_RE = STRING_PATTERNS["unicode_escape_seq"]
_CHARCODE_RE = STRING_PATTERNS["charcode_call"]
_BASE64_STRING_RE = STRING_PATTERNS["base64_quoted"]
_CONCAT_STRING_RE = STRING_PATTERNS["concat_chain"]

# Tokeniser used inside _reconstruct_concat to pull each quoted part out of a
# matched concat chain. Compiled once at module load (was recompiled on every
# concat match before).
_CONCAT_TOKEN_RE = re.compile(r'["\']([^"\']*)["\']')


class JSStringsExtractor(JSExtractor):

    def __init__(
        self, filepath, log, exporters=None, index_prefix=None,
        known_benign=False, known_malicious=False, source=None, context=None,
    ):
        super().__init__(
            filepath, log, exporters, index_prefix,
            known_benign, known_malicious, source, context=context,
        )
        self.string_findings = None
        self.log.debug(inspect.currentframe().f_code.co_name)

    def tag(self):
        return Tag.JS_STRINGS.value

    def _decode_hex_string(self, hex_str):
        """Decode \\x41\\x42 style hex strings."""
        try:
            # Remove \\x prefix and decode
            clean = hex_str.replace('\\x', '')
            return bytes.fromhex(clean).decode('utf-8', errors='replace')
        except Exception:
            return None

    def _decode_unicode_string(self, uni_str):
        """Decode \\u0041\\u0042 style unicode strings."""
        try:
            return uni_str.encode('utf-8').decode('unicode_escape')
        except Exception:
            return None

    def _decode_charcode(self, charcode_str):
        """Decode String.fromCharCode(72, 101, 108, ...) sequences."""
        try:
            codes = [int(c.strip()) for c in charcode_str.split(',') if c.strip().isdigit()]
            return ''.join(chr(c) for c in codes if 0 <= c <= 0x10FFFF)
        except Exception:
            return None

    def _decode_base64(self, b64_str):
        """Attempt to decode base64 string."""
        try:
            decoded = base64.b64decode(b64_str)
            # Check if result is printable text
            text = decoded.decode('utf-8', errors='strict')
            # Only return if it looks like text (>80% printable)
            printable = sum(1 for c in text if c.isprintable() or c in '\n\r\t')
            if printable / len(text) > 0.8:
                return text
        except Exception:
            pass
        return None

    def _reconstruct_concat(self, concat_match):
        """Reconstruct concatenated string parts."""
        try:
            parts = _CONCAT_TOKEN_RE.findall(concat_match)
            return ''.join(parts)
        except Exception:
            return None

    def _find_line_number(self, match_start):
        """1-indexed line number for `match_start`, looked up in O(log L) via
        bisect over `self._line_offsets` (built once per extract() call).

        Replaces the historical `self.js_source[:match_start].count('\\n') + 1`
        which was O(N) per call and quadratic across all matches in a sample.
        """
        return bisect.bisect_right(self._line_offsets, match_start)

    def _scan_text(self, text):
        """Run every encoded-string pattern over `text` and return a list of
        finding dicts. Stateless apart from the per-call `_line_offsets` cache,
        which `_find_line_number` reads — callers must reset it before invoking
        this so line numbers reference the text being scanned, not the previous
        one.
        """
        findings = []

        # Hex-encoded strings
        for m in _HEX_STRING_RE.finditer(text):
            raw = m.group()
            decoded = self._decode_hex_string(raw)
            if decoded and len(decoded) >= 4:
                findings.append({
                    'string': decoded[:4000],
                    'string_raw': raw[:4000],
                    'string_encoding': 'hex',
                    'string_offset': self._find_line_number(m.start()),
                    'string_length': len(decoded),
                    'string_raw_length': len(raw),
                    'string_entropy': self._calculate_text_entropy(decoded),
                })

        # Unicode-encoded strings
        for m in _UNICODE_STRING_RE.finditer(text):
            raw = m.group()
            decoded = self._decode_unicode_string(raw)
            if decoded and len(decoded) >= 3:
                findings.append({
                    'string': decoded[:4000],
                    'string_raw': raw[:4000],
                    'string_encoding': 'unicode',
                    'string_offset': self._find_line_number(m.start()),
                    'string_length': len(decoded),
                    'string_raw_length': len(raw),
                    'string_entropy': self._calculate_text_entropy(decoded),
                })

        # String.fromCharCode sequences
        for m in _CHARCODE_RE.finditer(text):
            raw = m.group()
            decoded = self._decode_charcode(m.group(1))
            if decoded and len(decoded) >= 4:
                findings.append({
                    'string': decoded[:4000],
                    'string_raw': raw[:4000],
                    'string_encoding': 'charcode',
                    'string_offset': self._find_line_number(m.start()),
                    'string_length': len(decoded),
                    'string_raw_length': len(raw),
                    'string_entropy': self._calculate_text_entropy(decoded),
                })

        # Base64-encoded strings
        for m in _BASE64_STRING_RE.finditer(text):
            raw = m.group(0)
            b64_val = m.group(1)
            decoded = self._decode_base64(b64_val)
            if decoded and len(decoded) >= 10:
                findings.append({
                    'string': decoded[:4000],
                    'string_raw': raw[:4000],
                    'string_encoding': 'base64',
                    'string_offset': self._find_line_number(m.start()),
                    'string_length': len(decoded),
                    'string_raw_length': len(raw),
                    'string_entropy': self._calculate_text_entropy(decoded),
                })

        # Concatenated strings (reassembled)
        for m in _CONCAT_STRING_RE.finditer(text):
            raw = m.group()
            reconstructed = self._reconstruct_concat(raw)
            if reconstructed and len(reconstructed) >= 20:
                findings.append({
                    'string': reconstructed[:4000],
                    'string_raw': raw[:4000],
                    'string_encoding': 'concat',
                    'string_offset': self._find_line_number(m.start()),
                    'string_length': len(reconstructed),
                    'string_raw_length': len(raw),
                    'string_entropy': self._calculate_text_entropy(reconstructed),
                })

        return findings

    def extract(self):
        src = self.js_source
        if not src:
            return None

        # Pass 1: raw source. _line_offsets is keyed off whichever text is
        # currently being scanned so _find_line_number resolves to that text.
        self._line_offsets = line_offsets(src)
        findings = self._scan_text(src)

        # Pass 2: deobfuscated text, when the deobfuscator produced something
        # meaningfully different. Same patterns, but a different surface — for
        # samples where the encoded payload is hidden behind an outer wrapper
        # (e.g. array.join() + eval in Vjw0rm/WSH-RAT) only this pass yields
        # any rows at all.
        deobf_text, _ = self._context.deobfuscated
        if deobf_text and deobf_text != src:
            self._line_offsets = line_offsets(deobf_text)
            findings.extend(self._scan_text(deobf_text))

        if not findings:
            return None

        # Deduplicate by decoded string value (raw pass wins on collision: it
        # comes first in `findings`). A string that surfaces only in the
        # deobfuscated text still gets persisted, which is the whole point of
        # the second pass.
        seen_values = set()
        deduped = []
        for f in findings:
            val_key = f['string'][:100]
            if val_key not in seen_values:
                seen_values.add(val_key)
                deduped.append(f)

        self.string_findings = deduped[:500]  # Limit per file
        # Publish to the shared context so post-loop consumers (notably the IOC
        # plumbing in workers.py) can scrape the decoded strings without
        # holding a reference to this extractor instance.
        self._context.decoded_strings = self.string_findings
        return self.string_findings

    def prepare_export_data(self, exporter_type: str) -> Any:
        if exporter_type == "ClickHouseExporter":
            if not self.string_findings:
                return None

            data = []
            for f in self.string_findings:
                data.append([
                    self.sha256,
                    f['string'],
                    f['string_raw'],
                    f['string_encoding'],
                    f['string_offset'],
                    f['string_length'],
                    f['string_raw_length'],
                    f['string_entropy'],
                ])

            column_names = [
                "sha256",
                "string",
                "string_raw",
                "string_encoding",
                "string_offset",
                "string_length",
                "string_raw_length",
                "string_entropy",
            ]

            column_type_names = [
                "FixedString(64)",
                "String",
                "String",
                "LowCardinality(String)",
                "UInt64",
                "UInt32",
                "UInt32",
                "Float32",
            ]

            return (data, column_names, column_type_names)

    def get_clickhouse_table(self) -> str:
        return "code_binja_strings_raw"