Rahul Mohanani

37 papers A* 1A 3B 2C 1Journal 16Unranked 14
YearRankTypeTitle / Venue / Authors
2026 J jnl
J. Syst. Softw.
Maha Sroor, Rahul Mohanani, Ricardo Colomo-Palacios, Sandun Dasanayake, Tommi Mikkonen
2025 C conf
APSEC
Maha Sroor, Teerath Das, Rahul Mohanani, Tommi Mikkonen
2025 J jnl
CoRR
Maha Sroor, Teerath Das, Rahul Mohanani, Tommi Mikkonen
2025 J jnl
CoRR
Anrafel Fernandes Pereira, Maria Teresa Baldassarre, Daniel Méndez, Jürgen Börstler, Nauman Bin Ali, Rahul Mohanani, Darja Smite, Stefan Biffl, Rogardt Heldal, Davide Falessi, Daniel Graziotin, Marcos Kalinowski
2025 J jnl
CoRR
Iftikhar Ahmad, Teemu Autto, Teerath Das, Joonas Hämäläinen, Pasi Jalonen, Viljami Järvinen, Harri Kallio, Tomi Kankainen, Taija Kolehmainen, Pertti Kontio, Pyry Kotilainen, Matti Kurittu, Tommi Mikkonen, Rahul Mohanani, Niko Mäkitalo, Jari Partanen, Roope Pajasmaa, Jarkko Pellikka, Manu Setälä, Jari Siukonen, Anssi Sorvisto, Maha Sroor, Teppo Suominen, Salla Timonen, Muhammad Waseem, Yuriy Yevstihnyeyev, Verneri Äberg, Leif Åstrand
2025 conf
CHASE@ICSE
Mary Sánchez-Gordón, Rahul Mohanani, Ricardo Colomo-Palacios
2025 J jnl
CoRR
Maha Sroor, Rahul Mohanani, Ricardo Colomo-Palacios, Sandun Dasanayake, Tommi Mikkonen
2025 J jnl
Inf. Softw. Technol.
Oleksandr Kosenkov, Parisa Elahidoost, Tony Gorschek, Jannik Fischbach, Daniel Méndez, Michael Unterkalmsteiner, Davide Fucci, Rahul Mohanani
2024 B conf
SEAA
Maha Sroor, Rahul Mohanani, Teerath Das, Tommi Mikkonen, Sandun Dasanayake
2024 conf
IWSiB@ICSE
Marianna Jantunen, Richard Meyes, Veronika Kurchyna, Tobias Meisen, Pekka Abrahamsson, Rahul Mohanani
2024 J jnl
CoRR
Oleksandr Kosenkov, Parisa Elahidoost, Tony Gorschek, Jannik Fischbach, Daniel Méndez, Michael Unterkalmsteiner, Davide Fucci, Rahul Mohanani
2023 conf
PROFES (1)
Salla Timonen, Maha Sroor, Rahul Mohanani, Tommi Mikkonen
2023 A conf
EASE
Mamia Agbese, Rahul Mohanani, Arif Ali Khan, Pekka Abrahamsson
2023 conf
IoT
Mamia Agbese, Niko Mäkitalo, Muhammad Waseem, Rahul Mohanani, Pekka Abrahamsson, Tommi Mikkonen
2023 conf
ICSOB
Timo Okker, Rahul Mohanani, Tommi P. Auvinen, Pekka Abrahamsson
2023 A conf
EASE
Mamia Agbese, Rahul Mohanani, Arif Ali Khan, Pekka Abrahamsson
2023 J jnl
CoRR
Mamia Agbese, Rahul Mohanani, Arif Ali Khan, Pekka Abrahamsson
2023 conf
ICSOB Companion
Joonas Himmanen, Xiaofeng Wang, Rahul Mohanani
2023 conf
ICSOB
Mamia Agbese, Erika Halme, Rahul Mohanani, Pekka Abrahamsson
2022 conf
iThings/GreenCom/CPSCom/SmartData/Cybermatics
Rebekah Rousi, Ville Vakkuri, Paulius Daubaris, Simo Linkola, Hooman Samani, Niko Mäkitalo, Erika Halme, Mamia Agbese, Rahul Mohanani, Tommi Mikkonen, Pekka Abrahamsson
2022 conf
ICSOB
Teemu Nieminen, Rahul Mohanani, Pekka Abrahamsson
2022 J jnl
IEEE Trans. Software Eng.
Rahul Mohanani, Paul Ralph, Burak Turhan, Vladimir Mandic
2022 conf
ICSOB
Mamia Ori-otse Agbese, Marko Rintamaki, Rahul Mohanani, Pekka Abrahamsson
2021 J jnl
IEEE Trans. Software Eng.
Rahul Mohanani, Burak Turhan, Paul Ralph
2020 J jnl
IEEE Trans. Software Eng.
Rahul Mohanani, Iflaah Salman, Burak Turhan, Pilar Rodríguez, Paul Ralph
2019 J jnl
CoRR
Rahul Mohanani, Burak Turhan, Paul Ralph
2019 A conf
ESEM
Fabian Fagerholm, Christoph Becker, Alexander Chatzigeorgiou, Stefanie Betz, Leticia Duboc, Birgit Penzenstadler, Rahul Mohanani, Colin C. Venters
2019 J jnl
CoRR
Fabian Fagerholm, Christoph Becker, Alexander Chatzigeorgiou, Stefanie Betz, Leticia Duboc, Birgit Penzenstadler, Rahul Mohanani, Colin C. Venters
2019 J jnl
CoRR
Christoph Becker, Fabian Fagerholm, Rahul Mohanani, Alexander Chatzigeorgiou
2019 conf
TechDebt@ICSE
Christoph Becker, Fabian Fagerholm, Rahul Mohanani, Alexander Chatzigeorgiou
2017 J jnl
CoRR
Rahul Mohanani, Iflaah Salman, Burak Turhan, Pilar Rodríguez, Paul Ralph
2017 B conf
SEAA
Rahul Mohanani, Prabhat Ram, Ahmed Lasisi, Paul Ralph, Burak Turhan
2016 conf
ICIT
Navin Kumar Paliwal, Rahul Mohanani, Navneet Kumar Singh, Asheesh Kumar Singh
2016 conf
ICSE (Companion Volume)
Rahul Mohanani
2015 J jnl
ACM SIGSOFT Softw. Eng. Notes
Rahul Mohanani
2015 conf
TwinPeaks@ICSE
Paul Ralph, Rahul Mohanani
2014 A* conf
ICSE
Rahul Mohanani, Paul Ralph, Ben Shreeve
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)