Naser Hossein Motlagh

49 papers A 2B 1C 2Journal 35Unranked 9
YearRankTypeTitle / Venue / Authors
2026 J jnl
Computer
Adeyinka Akintola, Jun Ma, Naser Hossein Motlagh, Georgios Bouloukakis, Huber Flores
2026 J jnl
Internet Things
Aygün Varol, Naser Hossein Motlagh, Mirka Leino, Sasu Tarkoma, Johanna Virkki
2026 J jnl
IEEE Internet Things Mag.
Naser Hossein Motlagh, Martha Arbayani Zaidan, Niko Mäkitalo, Petteri Nurmi, Sasu Tarkoma, Lauri Lovén
2025 J jnl
CoRR
Martha Arbayani Zaidan, Naser Hossein Motlagh, Petteri Nurmi, Tareq Hussein, Markku Kulmala, Tuukka Petäjä, Sasu Tarkoma
2025 A conf
MobiSys
Naser Hossein Motlagh, Martha Arbayani Zaidan, Matti Irjala, Andrew Rebeiro-Hargrave, Petteri Nurmi, Sasu Tarkoma
2025 J jnl
IEEE Pervasive Comput.
Alaa Saleh, Praveen Kumar Donta, Roberto Morabito, Naser Hossein Motlagh, Sasu Tarkoma, Lauri Lovén
2025 conf
QSW
Yangyang Wang, Praveen Kumar Donta, Lauri Lovén, Schahram Dustdar, Naser Hossein Motlagh
2025 A conf
MobiSys
Naser Hossein Motlagh, Martha Arbayani Zaidan, Pak Lun Fung, Samu Varjonen, Andrew Rebeiro-Hargrave, Petteri Nurmi, Sasu Tarkoma
2025 J jnl
CoRR
Alaa Saleh, Sasu Tarkoma, Praveen Kumar Donta, Naser Hossein Motlagh, Schahram Dustdar, Susanna Pirttikangas, Lauri Lovén
2025 conf
EDGE
Yangyang Wang, Alaa Saleh, Praveen Kumar Donta, Naser Hossein Motlagh, Lauri Lovén, Sasu Tarkoma, Schahram Dustdar
2024 J jnl
CoRR
Aygün Varol, Naser Hossein Motlagh, Mirka Leino, Sasu Tarkoma, Johanna Virkki
2024 J jnl
IEEE Internet Things J.
Naser Hossein Motlagh, Martha Arbayani Zaidan, Lauri Lovén, Pak Lun Fung, Tuomo Hänninen, Roberto Morabito, Petteri Nurmi, Sasu Tarkoma
2024 J jnl
IEEE Internet Things J.
Xiaoli Liu, Francesco Concas, Naser Hossein Motlagh, Martha Arbayani Zaidan, Pak Lun Fung, Samu Varjonen, Jarkko V. Niemi, Hilkka Timonen, Tareq Hussein, Tuukka Petäjä, Markku Kulmala, Petteri Nurmi, Sasu Tarkoma
2024 J jnl
CoRR
Alaa Saleh, Praveen Kumar Donta, Roberto Morabito, Naser Hossein Motlagh, Lauri Lovén
2024 J jnl
IEEE Consumer Electron. Mag.
Martha Arbayani Zaidan, Naser Hossein Motlagh, Behnam Zakeri, Tuukka Petäjä, Markku Kulmala, Sasu Tarkoma
2024 J jnl
IEEE Pervasive Comput.
Agustin Zuniga, Mayowa Olapade, Naser Hossein Motlagh, Mohan Liyanage, Zhigang Yin, Farooq Dar, Ngoc Thi Nguyen, Adeyinka Akintola, Marko Radeta, Sasu Tarkoma, Huber Flores, Petteri Nurmi
2024 conf
IoTDI
Huber Flores, Agustin Zuniga, Marko Radeta, Zhigang Yin, Mohan Liyanage, Naser Hossein Motlagh, Ngoc Thi Nguyen, Sasu Tarkoma, Moustafa Youssef, Petteri Nurmi
2023 conf
EnvSys@MobiSys
Naser Hossein Motlagh, Martha Arbayani Zaidan, Pak Lun Fung, Andrew Rebeiro-Hargrave, Matti Irjala, Tareq Hussein, Tuukka Petäjä, Petteri Nurmi, Sasu Tarkoma
2023 J jnl
IEEE Trans. Ind. Informatics
Martha Arbayani Zaidan, Naser Hossein Motlagh, Pak Lun Fung, Abedalaziz S. Khalaf, Yutaka Matsumi, Aijun Ding, Sasu Tarkoma, Tuukka Petäjä, Markku Kulmala, Tareq Hussein
2023 J jnl
IEEE Consumer Electron. Mag.
Naser Hossein Motlagh, Matti Irjala, Agustin Zuniga, Eemil Lagerspetz, Valtteri Rantala, Huber Flores, Petteri Nurmi, Sasu Tarkoma
2023 J jnl
IEEE Internet Things J.
Naser Hossein Motlagh, Pranvera Kortoçi, Xiang Su, Lauri Lovén, Hans Kristian Hoel, Sindre Bjerkestrand Haugsvær, Varun Srivastava, Casper Fabian Gulbrandsen, Petteri Nurmi, Sasu Tarkoma
2023 J jnl
IEEE Internet Things Mag.
Martha Arbayani Zaidan, Naser Hossein Motlagh, Brandon E. Boor, David V. Lu, Petteri Nurmi, Tuukka Petäjä, Aijun Ding, Markku Kulmala, Sasu Tarkoma, Tareq Hussein
2022 J jnl
CoRR
Henna Kokkonen, Lauri Lovén, Naser Hossein Motlagh, Juha Partala, Alfonso González-Gil, Ester Sola, Iñigo Angulo, Madhusanka Liyanage, Teemu Leppänen, Tri Nguyen, Panos Kostakos, Mehdi Bennis, Sasu Tarkoma, Schahram Dustdar, Susanna Pirttikangas, Jukka Riekki
2022 J jnl
Computer
Marko Radeta, Agustin Zuniga, Naser Hossein Motlagh, Mohan Liyanage, Rúben Freitas, Moustafa Youssef, Sasu Tarkoma, Huber Flores, Petteri Nurmi
2022 J jnl
Computer
Naser Hossein Motlagh, Lauri Lovén, Jacky Cao, Xiaoli Liu, Petteri Nurmi, Schahram Dustdar, Sasu Tarkoma, Xiang Su
2022 J jnl
IEEE Trans. Netw. Serv. Manag.
Naser Hossein Motlagh, Shubham Kapoor, Rola Alhalaseh, Sasu Tarkoma, Kimmo Hätönen
2022 J jnl
IEEE Pervasive Comput.
Agustin Zuniga, Naser Hossein Motlagh, Mohammad Ashraful Hoque, Sasu Tarkoma, Huber Flores, Petteri Nurmi
2022 J jnl
IEEE Internet Things J.
Agustin Zuniga, Naser Hossein Motlagh, Huber Flores, Petteri Nurmi
2022 J jnl
IEEE Pervasive Comput.
Zhigang Yin, Mayowa Olapade, Mohan Liyanage, Farooq Dar, Agustin Zuniga, Naser Hossein Motlagh, Xiang Su, Sasu Tarkoma, Pan Hui, Petteri Nurmi, Huber Flores
2021 J jnl
IEEE Access
Seyed Azad Nabavi, Naser Hossein Motlagh, Martha Arbayani Zaidan, Alireza Aslani, Behnam Zakeri
2021 J jnl
Proc. ACM Interact. Mob. Wearable Ubiquitous Technol.
Mikko Rinta-Homi, Naser Hossein Motlagh, Agustin Zuniga, Huber Flores, Petteri Nurmi
2021 J jnl
IEEE Internet Comput.
Xiang Su, Xiaoli Liu, Naser Hossein Motlagh, Jacky Cao, Peifeng Su, Petri Pellikka, Yongchun Liu, Tuukka Petäjä, Markku Kulmala, Pan Hui, Sasu Tarkoma
2021 conf
WF-IoT
Naser Hossein Motlagh, Pupu Toivonen, Martha Arbayani Zaidan, Eemil Lagerspetz, Ella Peltonen, Ekaterina Gilman, Petteri Nurmi, Sasu Tarkoma
2021 J jnl
IEEE Internet Things Mag.
Huber Flores, Naser Hossein Motlagh, Agustin Zuniga, Mohan Liyanage, Monica Passananti, Sasu Tarkoma, Moustafa Youssef, Petteri Nurmi
2021 J jnl
IEEE Netw.
Naser Hossein Motlagh, Ibrahim Afolabi, Matteo Pozza, Miloud Bagaa, Tarik Taleb, Sasu Tarkoma, Hannu Flinck
2020 conf
DroNet@MobiSys
Huber Flores, Agustin Zuniga, Naser Hossein Motlagh, Mohan Liyanage, Monica Passananti, Sasu Tarkoma, Moustafa Youssef, Petteri Nurmi
2020 J jnl
CoRR
Huber Flores, Naser Hossein Motlagh, Agustin Zuniga, Mohan Liyanage, Monica Passananti, Sasu Tarkoma, Moustafa Youssef, Petteri Nurmi
2020 J jnl
IEEE Commun. Mag.
Naser Hossein Motlagh, Tuukka Petäjä, Markku Kulmala, Sasu Tarkoma, Eemil Lagerspetz, Petteri Nurmi, Xin Li, Samu Varjonen, Julien Mineraud, Matti Siekkinen, Andrew Rebeiro-Hargrave, Tareq Hussein
2019 J jnl
IEEE Access
Siavash H. Khajavi, Naser Hossein Motlagh, Alireza Jaribion, Liss C. Werner, Jan Holmström
2019 J jnl
IEEE Internet Things J.
Naser Hossein Motlagh, Miloud Bagaa, Tarik Taleb
2019 C conf
INDIN
Naser Hossein Motlagh, Petteri Nurmi, Sasu Tarkoma, Martha Arbayani Zaidan, Eemil Lagerspetz, Samu Varjonen, Juhani Toivonen, Julien Mineraud, Andrew Rebeiro-Hargrave, Matti Siekkinen, Tareq Hussein
2019 C conf
INDIN
Eemil Lagerspetz, Sasu Tarkoma, Tareq Hussein, Naser Hossein Motlagh, Martha Arbayani Zaidan, Pak Lun Fung, Julien Mineraud, Samu Varjonen, Matti Siekkinen, Petteri Nurmi, Yutaka Matsumi
2018 conf
SOCA
Naser Hossein Motlagh, Siavash H. Khajavi, Alireza Jaribion, Jan Holmström
2018 conf
SOCA
Alireza Jaribion, Siavash H. Khajavi, Naser Hossein Motlagh, Jan Holmström
2017 conf
ICC
Naser Hossein Motlagh, Miloud Bagaa, Tarik Taleb, JaeSeung Song
2017 J jnl
IEEE Commun. Mag.
Naser Hossein Motlagh, Miloud Bagaa, Tarik Taleb
2016 J jnl
IEEE Internet Things J.
Naser Hossein Motlagh, Tarik Taleb, Osama Arouk
2016 B conf
GLOBECOM
Naser Hossein Motlagh, Miloud Bagaa, Tarik Taleb
2010 J jnl
Int. J. Commun. Netw. Syst. Sci.
Yang Liu, Naser Hossein Motlagh
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"