Rahul Sarpeshkar

84 papers A* 1C 16Journal 53Unranked 14
YearRankTypeTitle / Venue / Authors
2025 J jnl
IEEE Trans. Comput. Biol. Bioinform.
Douglas Raymond Beahm, Thomas M. Deangelo, Shouka Tavakolian, Rahul Sarpeshkar
2023 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Haixiang Zhao, Rahul Sarpeshkar, Soumyajit Mandal
2023 J jnl
IEEE Trans. Mol. Biol. Multi Scale Commun.
Douglas Raymond Beahm, Yijie Deng, Thomas M. Deangelo, Rahul Sarpeshkar
2023 conf
BioCAS
Douglas Raymond Beahm, Joao Pedro Teuber Carvalho, Thomas M. Deangelo, Rahul Sarpeshkar
2022 J jnl
Neural Comput.
A. J. Cressman, Woradorn Wattanapanitch, I. Chuang, Rahul Sarpeshkar
2021 conf
MWSCAS
Haixiang Zhao, Rahul Sarpeshkar, Soumyajit Mandal
2020 J jnl
PLoS Comput. Biol.
J. Kyle Medley, Jonathan J. Y. Teo, Sung Sik Woo, Joseph L. Hellerstein, Rahul Sarpeshkar, Herbert M. Sauro
2019 J jnl
IEEE Trans. Biomed. Circuits Syst.
Jonathan J. Y. Teo, Ron Weiss, Rahul Sarpeshkar
2019 conf
BioCAS
Jonathan J. Y. Teo, Jaewook Kim, Sung Sik Woo, Rahul Sarpeshkar
2018 J jnl
IEEE Trans. Biomed. Circuits Syst.
Sung Sik Woo, Jaewook Kim, Rahul Sarpeshkar
2018 J jnl
IEEE Trans. Biomed. Circuits Syst.
Jaewook Kim, Sung Sik Woo, Rahul Sarpeshkar
2017 conf
MWSCAS
Todd Thorsen, Isaac Weaver, Eric Holihan, Rahul Sarpeshkar
2016 A* conf
PLDI
Sara Achour, Rahul Sarpeshkar, Martin C. Rinard
2015 J jnl
IEEE Trans. Biomed. Circuits Syst.
Sung Sik Woo, Jaewook Kim, Rahul Sarpeshkar
2015 J jnl
IEEE Trans. Biomed. Circuits Syst.
Rahul Sarpeshkar
2015 J jnl
IEEE Trans. Biomed. Circuits Syst.
Jonathan J. Y. Teo, Sung Sik Woo, Rahul Sarpeshkar
2014 J jnl
IEEE Trans. Biomed. Circuits Syst.
Manel Gasulla, Joan Albesa, Michael W. Baker, Rahul Sarpeshkar
2013 C conf
ISCAS
Sung Sik Woo, Rahul Sarpeshkar
2012 J jnl
IEEE Trans. Biomed. Circuits Syst.
Scott K. Arfin, Rahul Sarpeshkar
2012 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Rahul Sarpeshkar
2011 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Soumyajit Mandal, Rahul Sarpeshkar
2011 J jnl
IEEE Trans. Biomed. Circuits Syst.
Woradorn Wattanapanitch, Rahul Sarpeshkar
2011 J jnl
IEEE Trans. Biomed. Circuits Syst.
Bruno Do Valle, Christian T. Wentz, Rahul Sarpeshkar
2011 J jnl
IEEE Trans. Biomed. Circuits Syst.
Keng Hoong Wee, Lorenzo Turicchia, Rahul Sarpeshkar
2010 J jnl
IEEE Pervasive Comput.
Soumyajit Mandal, Lorenzo Turicchia, Rahul Sarpeshkar
2010 C conf
ISCAS
Soumyajit Mandal, Rahul Sarpeshkar
2010 C conf
BSN
Keng Hoong Wee, Lorenzo Turicchia, Rahul Sarpeshkar
2010 J jnl
IEEE Trans. Biomed. Circuits Syst.
Maziar Tavakoli, Lorenzo Turicchia, Rahul Sarpeshkar
2010 C conf
ISCAS
Bruno Do Valle, Christian T. Wentz, Rahul Sarpeshkar
2010 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Lorenzo Turicchia, Bruno Do Valle, Jose L. Bohorquez, William R. Sanchez, Vinith Misra, Leon Fay, Maziar Tavakoli, Rahul Sarpeshkar
2009 C conf
BSN
Soumyajit Mandal, Lorenzo Turicchia, Rahul Sarpeshkar
2009 J jnl
IEEE J. Solid State Circuits
Soumyajit Mandal, Serhii M. Zhak, Rahul Sarpeshkar
2009 J jnl
IEEE Trans. Biomed. Circuits Syst.
Leon Fay, Vinith Misra, Rahul Sarpeshkar
2009 C conf
ISCAS
Scott K. Arfin, Soumyajit Mandal, Rahul Sarpeshkar
2009 C conf
ISCAS
Soumyajit Mandal, Rahul Sarpeshkar
2009 conf
CICC
Lorenzo Turicchia, Soumyajit Mandal, Maziar Tavakoli, Leon Fay, Vinith Misra, Jose L. Bohorquez, William R. Sanchez, Rahul Sarpeshkar
2008 J jnl
IEEE Pervasive Comput.
Ji-Jon Sit, Rahul Sarpeshkar
2008 J jnl
IEEE Trans. Biomed. Circuits Syst.
Keng Hoong Wee, Lorenzo Turicchia, Rahul Sarpeshkar
2008 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Keng Hoong Wee, Rahul Sarpeshkar
2008 J jnl
IEEE Trans. Biomed. Circuits Syst.
Rahul Sarpeshkar, Woradorn Wattanapanitch, Scott K. Arfin, Benjamin I. Rapoport, Soumyajit Mandal, Michael W. Baker, Michale S. Fee, Sam Musallam, Richard A. Andersen
2008 J jnl
IEEE Trans. Biomed. Circuits Syst.
Soumyajit Mandal, Rahul Sarpeshkar
2007 J jnl
IEEE Trans. Biomed. Eng.
Ji-Jon Sit, Andrea M. Simonson, Andrew J. Oxenham, Michael A. Faltys, Rahul Sarpeshkar
2007 J jnl
IEEE Trans. Biomed. Circuits Syst.
Ji-Jon Sit, Rahul Sarpeshkar
2007 J jnl
IEEE Trans. Biomed. Circuits Syst.
Woradorn Wattanapanitch, Michale S. Fee, Rahul Sarpeshkar
2007 J jnl
EURASIP J. Audio Speech Music. Process.
Bhiksha Raj, Lorenzo Turicchia, Bent Schmidt-Nielsen, Rahul Sarpeshkar
2007 J jnl
IEEE Trans. Biomed. Circuits Syst.
Michael W. Baker, Rahul Sarpeshkar
2007 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Soumyajit Mandal, Rahul Sarpeshkar
2007 C conf
ISCAS
Rahul Sarpeshkar, Woradorn Wattanapanitch, Benjamin I. Rapoport, Scott K. Arfin, Michael W. Baker, Soumyajit Mandal, Michale S. Fee, Sam Musallam, Richard A. Andersen
2006 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Heemin Y. Yang, Rahul Sarpeshkar
2006 C conf
ISCAS
Micah G. O'Halloran, Rahul Sarpeshkar
2006 C conf
ISCAS
Soumyajit Mandal, Serhii M. Zhak, Rahul Sarpeshkar
2006 C conf
ISCAS
Soumyajit Mandal, Scott K. Arfin, Rahul Sarpeshkar
2006 C conf
BSN
Rahul Sarpeshkar
2006 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Christopher D. Salthouse, Rahul Sarpeshkar
2006 J jnl
IEEE J. Solid State Circuits
Michael W. Baker, Rahul Sarpeshkar
2006 C conf
ISCAS
Byungsub Kim, Soumyajit Mandal, Rahul Sarpeshkar
2006 J jnl
IEEE J. Solid State Circuits
Maziar Tavakoli, Rahul Sarpeshkar
2005 conf
ICASSP (1)
Jethran Guinness, Bhiksha Raj, Bent Schmidt-Nielsen, Lorenzo Turicchia, Rahul Sarpeshkar
2005 J jnl
IEEE Trans. Speech Audio Process.
Lorenzo Turicchia, Rahul Sarpeshkar
2005 J jnl
IEEE J. Solid State Circuits
Maziar Tavakoli, Rahul Sarpeshkar
2005 J jnl
IEEE J. Solid State Circuits
Heemin Y. Yang, Rahul Sarpeshkar
2005 J jnl
IEEE Trans. Biomed. Eng.
Rahul Sarpeshkar, Christopher D. Salthouse, Ji-Jon Sit, Michael W. Baker, Serhii M. Zhak, Timothy Kuan-Ta Lu, Lorenzo Turicchia, Stephanie Balster
2005 conf
ISCAS (3)
Keng Hoong Wee, Ji-Jon Sit, Rahul Sarpeshkar
2004 J jnl
IEEE J. Solid State Circuits
Micah G. O'Halloran, Rahul Sarpeshkar
2004 C conf
ACC
Michael W. Baker, Timothy Kuan-Ta Lu, Rahul Sarpeshkar
2004 J jnl
IEEE J. Solid State Circuits
Ji-Jon Sit, Rahul Sarpeshkar
2003 conf
CICC
Michael W. Baker, Timothy Kuan-Ta Lu, Christopher D. Salthouse, Ji-Jon Sit, Serhii M. Zhak, Rahul Sarpeshkar
2003 J jnl
IEEE J. Solid State Circuits
Michael W. Baker, Rahul Sarpeshkar
2003 J jnl
IEEE J. Solid State Circuits
Serhii M. Zhak, Michael W. Baker, Rahul Sarpeshkar
2003 conf
ISCAS (5)
Timothy Kuan-Ta Lu, Michael W. Baker, Christopher D. Salthouse, Ji-Jon Sit, Serhii M. Zhak, Rahul Sarpeshkar
2003 conf
ISCAS (5)
Michael W. Baker, Serhii M. Zhak, Rahul Sarpeshkar
2003 J jnl
IEEE J. Solid State Circuits
Christopher D. Salthouse, Rahul Sarpeshkar
2003 J jnl
IEEE J. Solid State Circuits
Maziar Tavakoli, Rahul Sarpeshkar
2003 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Alex C. H. MeVay, Rahul Sarpeshkar
2002 conf
ISCAS (1)
Maziar Tavakoli Dastjerdi, Rahul Sarpeshkar
2002 conf
ISCAS (5)
Christopher D. Salthouse, Rahul Sarpeshkar
2002 J jnl
Neural Comput.
Rahul Sarpeshkar, Micah G. O'Halloran
2000 C conf
ISCAS
Rahul Sarpeshkar, R. Herrera, H. Yang
1999 conf
ISCAS (5)
Rahul Sarpeshkar
1998 J jnl
Neural Comput.
Rahul Sarpeshkar
1996 J jnl
Proc. IEEE
Rahul Sarpeshkar, Jörg Kramer, Giacomo Indiveri, Christof Koch
1995 C conf
ISCAS
Jörg Kramer, Rahul Sarpeshkar, Christof Koch
1992 conf
NIPS
Rahul Sarpeshkar, Wyeth Bair, Christof Koch
1991 J jnl
IEEE J. Solid State Circuits
Rahul Sarpeshkar, John L. Wyatt Jr., Nicky C. Lu, Porter D. Gerber
redb/extractors/decompiler/apk/method_extractor.py
← Index redb/extractors/decompiler/apk/method_extractor.py python
"""Per-method content extraction, hashing, and similarity computation.

Handles SHA-256 content hashing, ssdeep/TLSH fuzzy hashing, MinHash
computation, and obfuscation indicator detection for APK methods.
"""

import hashlib
import re
from typing import Dict, List, Optional

from redb.extractors.decompiler.apk.smali_normalization import (
    categorize_opcode,
    normalize_method_body,
)
from redb.extractors.decompiler.apk.smali_parser import SmaliParser


# ---------------------------------------------------------------------------
# Smali Prime Product — semantic primes matching Binary Ninja's LLIL primes
# ---------------------------------------------------------------------------
# Each Dalvik semantic category maps to the same prime its LLIL counterpart
# uses in cfg_features.py. This makes prime products semantically comparable
# for APK-vs-APK similarity (not numerically comparable to Binja values).

SMALI_OP_PRIMES = {
    "ALU": 37,       # ADD/SUB → same prime as LLIL_ADD
    "CONV": 131,     # Type conversions → same as LLIL_SX
    "CMP": 103,      # Comparisons → same as LLIL_CMP_E
    "MOV": 2,        # Register moves → same as LLIL_SET_REG
    "CONST": 2,      # Constants → SET_REG equivalent
    "LOAD": 5,       # Field/array reads → same as LLIL_LOAD
    "STORE": 7,      # Field/array writes → same as LLIL_STORE
    "CALL": 17,      # invoke-* → same as LLIL_CALL
    "BRANCH": 29,    # if-* → same as LLIL_IF
    "JMP": 31,       # goto → same as LLIL_GOTO
    "SWITCH": 151,   # switch → same as LLIL_JUMP_TO
    "RET": 23,       # return → same as LLIL_RET
    "ALLOC": 5,      # new-instance/new-array → LOAD-adjacent (heap access)
    "TYPE": 1,       # check-cast/instance-of → identity (metadata)
    "ARR": 5,        # array-length/fill-array → LOAD-adjacent
    "EXC": 23,       # throw → RET-adjacent (control transfer out)
    "SYNC": 1,       # monitor → identity (no LLIL equivalent)
    "OTHER": 1,      # Unknown → identity
}


def compute_prime_product_smali(smali_body: str) -> int:
    """Multiplicative hash of normalized Dalvik opcodes. Mod 2^64.

    Same algorithm as cfg_features.compute_prime_product but using
    Dalvik semantic categories instead of LLIL operation enums.
    """
    if not smali_body:
        return 0

    product = 1
    for line in smali_body.splitlines():
        stripped = line.strip()
        if not stripped or stripped.startswith((".", ":", "#")):
            continue
        opcode = stripped.split()[0].split("/")[0] if stripped else ""
        category = categorize_opcode(opcode)
        prime = SMALI_OP_PRIMES.get(category, 1)
        product = (product * prime) % (2**64)

    return product


def count_call_instructions(smali_body: str) -> int:
    """Count invoke-* instructions in a smali method body."""
    if not smali_body:
        return 0
    count = 0
    for line in smali_body.splitlines():
        stripped = line.strip()
        if stripped.startswith("invoke-"):
            count += 1
    return count


def compute_sha256(content: str) -> str:
    """Compute SHA-256 hash of normalized content."""
    return hashlib.sha256(content.encode("utf-8")).hexdigest()


def compute_ssdeep(content: str) -> Optional[str]:
    """Compute ssdeep fuzzy hash of content."""
    try:
        import ppdeep
        data = content.encode("utf-8")
        if len(data) < 50:
            return None
        result = ppdeep.hash(data)
        return result if result else None
    except (ImportError, Exception):
        return None


def compute_tlsh(content: str) -> Optional[str]:
    """Compute TLSH fuzzy hash of content."""
    try:
        import tlsh
        data = content.encode("utf-8")
        if len(data) < 50:
            return None
        result = tlsh.hash(data)
        return result if result else None
    except (ImportError, Exception):
        return None


def compute_minhash(
    content: str,
    n: int = 3,
    normalization_level: str = "opcode_api",
) -> Optional[List[int]]:
    """Compute MinHash signature from semantically normalized smali n-grams.

    Applies semantic normalization (analogous to Binary Ninja's LLIL) before
    computing the MinHash. This strips register allocation noise and
    instruction encoding variants while preserving operation semantics and
    API references.

    Uses the same algorithm and parameters as the Binary Ninja MinHasher
    (64 seeds from master seed 0xdeadbeef, 8-bit signature elements, mmh3)
    to ensure cross-platform similarity comparisons are compatible.

    Args:
        content: Raw smali method body.
        n: N-gram size (default 3).
        normalization_level: Normalization level for instructions.
            'opcode_api' (default) preserves API call/field references.
            'category' uses only semantic categories.
            'opcode' uses base opcodes without operands.
    """
    try:
        import mmh3
    except ImportError:
        return None

    HASH_MAX = 0xFFFFFFFF
    SIGNATURE_LENGTH = 64
    SIGNATURE_BITS = 8

    # Semantically normalize instructions (like LLIL for native code)
    lines = normalize_method_body(content, level=normalization_level)

    if len(lines) < n:
        return None

    # Build n-grams (tuples of normalized instruction strings)
    shingles = [tuple(lines[i:i + n]) for i in range(len(lines) - n + 1)]

    if not shingles:
        return None

    # Generate deterministic seeds matching the Binary Ninja pipeline
    import random
    rng = random.Random(0xDEADBEEF)
    seeds = [rng.randint(0, HASH_MAX) for _ in range(SIGNATURE_LENGTH)]

    # For each seed, hash all shingles and take the minimum
    signature = []
    for seed in seeds:
        min_val = HASH_MAX
        for shingle in shingles:
            text = "|".join(str(elem) for elem in shingle)
            h = mmh3.hash(text, seed) & HASH_MAX
            if h < min_val:
                min_val = h
        # Truncate to signature bits
        if SIGNATURE_BITS < 32:
            min_val %= (2 ** SIGNATURE_BITS)
        signature.append(min_val)

    return signature


def detect_obfuscation_indicators(
    method_name: str,
    class_name: str,
    smali_body: str,
    instruction_count: int,
) -> Dict[str, bool]:
    """Compute obfuscation indicators for a method.

    Returns dict with boolean indicators.
    """
    indicators = {}

    # Short method name (typical R8/ProGuard output)
    indicators["short_method_name"] = len(method_name) <= 2

    # Short class name — extract simple name from Dalvik descriptor
    simple_class = class_name
    if "/" in simple_class:
        simple_class = simple_class.rsplit("/", 1)[-1]
    simple_class = simple_class.rstrip(";")
    indicators["short_class_name"] = len(simple_class) <= 2

    # String encryption: const-string followed by decryption-pattern call
    indicators["has_string_encryption"] = _detect_string_encryption(smali_body)

    # Reflection calls
    indicators["has_reflection_calls"] = _detect_reflection_calls(smali_body)

    # Excessive goto count (control flow flattening)
    goto_count = _count_goto_instructions(smali_body)
    threshold = max(5, int(instruction_count * 0.15))
    indicators["excessive_goto_count"] = goto_count > threshold

    return indicators


def _detect_string_encryption(smali_body: str) -> bool:
    """Detect const-string followed by decryption-pattern calls."""
    lines = smali_body.split("\n")
    for i, line in enumerate(lines):
        stripped = line.strip()
        if stripped.startswith("const-string"):
            # Check the next 3 lines for invoke-* to potential decryption
            for j in range(i + 1, min(i + 4, len(lines))):
                next_line = lines[j].strip()
                if next_line.startswith("invoke-"):
                    # Common decryption patterns
                    if any(
                        pat in next_line
                        for pat in [
                            "decrypt",
                            "decode",
                            "Cipher",
                            "DES",
                            "AES",
                            "Base64",
                            "getBytes",
                        ]
                    ):
                        return True
    return False


def _detect_reflection_calls(smali_body: str) -> bool:
    """Detect use of Java reflection APIs."""
    reflection_patterns = [
        "Ljava/lang/reflect/",
        "Ljava/lang/Class;->forName",
        "Ljava/lang/Class;->getMethod",
        "Ljava/lang/Class;->getDeclaredMethod",
        "Ljava/lang/Class;->getField",
        "Ljava/lang/Class;->getDeclaredField",
    ]
    for pattern in reflection_patterns:
        if pattern in smali_body:
            return True
    return False


def _count_goto_instructions(smali_body: str) -> int:
    """Count goto/goto_16/goto_32 instructions."""
    count = 0
    for line in smali_body.split("\n"):
        stripped = line.strip()
        if stripped.startswith(("goto ", "goto/16 ", "goto/32 ")):
            count += 1
        elif stripped in ("goto", "goto/16", "goto/32"):
            count += 1
    return count


def dalvik_to_java_class(descriptor: str) -> str:
    """Convert Dalvik class descriptor to Java dot notation.

    Lcom/example/Foo; -> com.example.Foo
    """
    if descriptor.startswith("L") and descriptor.endswith(";"):
        return descriptor[1:-1].replace("/", ".")
    return descriptor.replace("/", ".")


def dalvik_type_to_java(type_desc: str) -> str:
    """Convert a Dalvik type descriptor to Java type name."""
    type_map = {
        "V": "void",
        "Z": "boolean",
        "B": "byte",
        "S": "short",
        "C": "char",
        "I": "int",
        "J": "long",
        "F": "float",
        "D": "double",
    }

    if not type_desc:
        return "void"

    if type_desc in type_map:
        return type_map[type_desc]

    if type_desc.startswith("["):
        return dalvik_type_to_java(type_desc[1:]) + "[]"

    if type_desc.startswith("L") and type_desc.endswith(";"):
        full = type_desc[1:-1].replace("/", ".")
        # Return simple name
        return full.rsplit(".", 1)[-1] if "." in full else full

    return type_desc


def dalvik_to_java_prototype(
    method_name: str, signature: str, class_name: str = ""
) -> str:
    """Convert Dalvik method signature to Java-style prototype.

    Input: method_name='onCreate', signature='(Landroid/os/Bundle;)V'
    Output: 'void onCreate(Bundle)'
    """
    # Parse return type and param types from signature
    if not signature or not signature.startswith("("):
        return f"void {method_name}()"

    close_paren = signature.find(")")
    if close_paren == -1:
        return f"void {method_name}()"

    params_str = signature[1:close_paren]
    return_type_str = signature[close_paren + 1:]

    return_type = dalvik_type_to_java(return_type_str)
    params = _parse_dalvik_params(params_str)
    param_java = ", ".join(dalvik_type_to_java(p) for p in params)

    return f"{return_type} {method_name}({param_java})"


def _parse_dalvik_params(params_str: str) -> List[str]:
    """Parse Dalvik parameter descriptor string into individual types."""
    params = []
    i = 0
    while i < len(params_str):
        ch = params_str[i]
        if ch in "VZBSCIJFD":
            params.append(ch)
            i += 1
        elif ch == "[":
            # Array — find the base type
            array_prefix = "["
            i += 1
            while i < len(params_str) and params_str[i] == "[":
                array_prefix += "["
                i += 1
            if i < len(params_str):
                if params_str[i] == "L":
                    end = params_str.find(";", i)
                    if end != -1:
                        params.append(array_prefix + params_str[i : end + 1])
                        i = end + 1
                    else:
                        break
                else:
                    params.append(array_prefix + params_str[i])
                    i += 1
        elif ch == "L":
            end = params_str.find(";", i)
            if end != -1:
                params.append(params_str[i : end + 1])
                i = end + 1
            else:
                break
        else:
            i += 1
    return params