Rajesh Hemant Chitnis

32 papers A* 6A 1B 5Journal 17Unranked 3
YearRankTypeTitle / Venue / Authors
2020 J jnl
SIAM J. Comput.
Rajesh Hemant Chitnis, Andreas Emil Feldmann, Mohammad Taghi Hajiaghayi, Dániel Marx
2015 J jnl
CoRR
Rajesh Hemant Chitnis, Hossein Esfandiari, MohammadTaghi Hajiaghayi, Rohit Khandekar, Guy Kortsarz, Saeed Seddighin
2015 B conf
SPAA
Rajesh Hemant Chitnis, Graham Cormode, Hossein Esfandiari, MohammadTaghi Hajiaghayi, Morteza Monemizadeh
2015 J jnl
ACM Trans. Algorithms
Rajesh Hemant Chitnis, Marek Cygan, Mohammad Taghi Hajiaghayi, Dániel Marx
2015 J jnl
CoRR
Rajesh Hemant Chitnis, Graham Cormode, Hossein Esfandiari, MohammadTaghi Hajiaghayi, Andrew McGregor, Morteza Monemizadeh, Sofya Vorotnikova
2015 A* conf
SODA
Rajesh Hemant Chitnis, Graham Cormode, Mohammad Taghi Hajiaghayi, Morteza Monemizadeh
2015 J jnl
SIGACT News
Rajesh Hemant Chitnis
2014 B conf
IPEC
Rajesh Hemant Chitnis, Hossein Esfandiari, MohammadTaghi Hajiaghayi, Rohit Khandekar, Guy Kortsarz, Saeed Seddighin
2014 J jnl
CoRR
Rajesh Hemant Chitnis, Graham Cormode, Mohammad Taghi Hajiaghayi, Morteza Monemizadeh
2014 A* conf
SODA
Rajesh Hemant Chitnis, MohammadTaghi Hajiaghayi, Dániel Marx
2013 B conf
SPAA
Rajesh Hemant Chitnis, MohammadTaghi Hajiaghayi, Jonathan Katz, Koyel Mukherjee
2013 B conf
IPEC
Rajesh Hemant Chitnis, Fedor V. Fomin, Daniel Lokshtanov, Pranabendu Misra, M. S. Ramanujan, Saket Saurabh
2013 J jnl
SIAM J. Comput.
Rajesh Hemant Chitnis, MohammadTaghi Hajiaghayi, Dániel Marx
2013 B conf
IPEC
Rajesh Hemant Chitnis, MohammadTaghi Hajiaghayi, Guy Kortsarz
2013 J jnl
CoRR
Rajesh Hemant Chitnis, MohammadTaghi Hajiaghayi, Guy Kortsarz
2013 A conf
ESA
Rajesh Hemant Chitnis, László Egri, Dániel Marx
2013 J jnl
CoRR
Rajesh Hemant Chitnis, László Egri, Dániel Marx
2013 J jnl
Graphs Comb.
L. Sunil Chandran, Rajesh Hemant Chitnis, Ramanjit Kumar
2013 J jnl
CoRR
Rajesh Hemant Chitnis, Fedor V. Fomin, Petr A. Golovach
2013 conf
FSTTCS
Rajesh Hemant Chitnis, Fedor V. Fomin, Petr A. Golovach
2013 J jnl
CoRR
Rajesh Hemant Chitnis, Fedor V. Fomin, Petr A. Golovach
2013 A* conf
AAAI
Rajesh Hemant Chitnis, Fedor V. Fomin, Petr A. Golovach
2012 J jnl
CoRR
Rajesh Hemant Chitnis, MohammadTaghi Hajiaghayi, Jonathan Katz, Koyel Mukherjee
2012 A* conf
FOCS
Rajesh Hemant Chitnis, Marek Cygan, MohammadTaghi Hajiaghayi, Marcin Pilipczuk, Michal Pilipczuk
2012 J jnl
CoRR
Rajesh Hemant Chitnis, Marek Cygan, MohammadTaghi Hajiaghayi, Marcin Pilipczuk, Michal Pilipczuk
2012 conf
ICALP (1)
Rajesh Hemant Chitnis, Marek Cygan, Mohammad Taghi Hajiaghayi, Dániel Marx
2012 J jnl
CoRR
Rajesh Hemant Chitnis, Marek Cygan, MohammadTaghi Hajiaghayi, Dániel Marx
2012 A* conf
SODA
Rajesh Hemant Chitnis, MohammadTaghi Hajiaghayi, Dániel Marx
2011 J jnl
CoRR
Rajesh Hemant Chitnis, MohammadTaghi Hajiaghayi, Dániel Marx
2011 J jnl
CoRR
Rajesh Hemant Chitnis, MohammadTaghi Hajiaghayi, Vahid Liaghat
2011 A* conf
AAAI
Rajesh Hemant Chitnis, MohammadTaghi Hajiaghayi, Vahid Liaghat
2010 conf
ISAAC (1)
Abhijin Adiga, Rajesh Hemant Chitnis, Saket Saurabh
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)