Mansoor A. S. Saqi

28 papers B 2Journal 23Unranked 3
YearRankTypeTitle / Venue / Authors
2019 J jnl
Briefings Bioinform.
Mansoor A. S. Saqi, Artem Lysenko, Yike Guo, Tatsuhiko Tsunoda, Charles Auffray
2018 J jnl
BMC Syst. Biol.
Bertrand De Meulder, Diane Lefaudeux, Aruna T. Bansal, Alexander Mazein, Amphun Chaiboonchoe, Hassan Ahmed, Irina Balaur, Mansoor A. S. Saqi, Johann Pellet, Stéphane Ballereau, Nathanaël Lemonnier, Kai Sun, Ioannis Pandis, Xian Yang, Manohara Batuwitage, Kosmas Kretsos, Jonathan van Eyll, Alun Bedding, Timothy Davison, Paul Dodson, Christopher Larminie, Anthony D. Postle, Julie Corfield, Ratko Djukanovic, Kian Fan Chung, Ian M. Adcock, Yike Guo, Peter J. Sterk, Alexander Manta, Anthony Rowe, Frédéric Baribaud, Charles Auffray
2017 J jnl
J. Comput. Biol.
Irina Balaur, Mansoor A. S. Saqi, Ana Barat, Artem Lysenko, Alexander Mazein, Christopher J. Rawlings, Heather J. Ruskin, Charles Auffray
2017 J jnl
Bioinform.
Irina Balaur, Alexander Mazein, Mansoor A. S. Saqi, Artem Lysenko, Christopher J. Rawlings
2016 J jnl
BioData Min.
Artem Lysenko, Irina A. Roznovat, Mansoor A. S. Saqi, Alexander Mazein, Christopher J. Rawlings, Charles Auffray
2016 J jnl
BMC Bioinform.
Vasundra Touré, Alexander Mazein, Dagmar Waltemath, Irina Balaur, Mansoor A. S. Saqi, Ron Henkel, Johann Pellet, Charles Auffray
2014 J jnl
Int. J. Data Min. Bioinform.
Richard J. B. Dobson, Patricia B. Munroe, Mark J. Caulfield, Mansoor A. S. Saqi
2013 B conf
IDA
Valeria Bo, Artem Lysenko, Mansoor A. S. Saqi, Dimah Z. Habash, Allan Tucker
2012 conf
CMSB
Laura Bennett, Artem Lysenko, Lazaros G. Papageorgiou, Martin Urban, Kim E. Hammond-Kosack, Christopher J. Rawlings, Mansoor A. S. Saqi, Sophia Tsoka
2011 J jnl
BMC Bioinform.
Michael Defoin-Platel, Matthew Morritt Hindle, Artem Lysenko, Stephen J. Powers, Dimah Z. Habash, Christopher J. Rawlings, Mansoor A. S. Saqi
2011 J jnl
BMC Bioinform.
Artem Lysenko, Michael Defoin-Platel, Keywan Hassani-Pak, Jan Taubert, Charlie Hodgman, Christopher J. Rawlings, Mansoor A. S. Saqi
2010 J jnl
Briefings Bioinform.
Artem Lysenko, Matthew Morritt Hindle, Jan Taubert, Mansoor A. S. Saqi, Christopher J. Rawlings
2010 conf
DILS
Fabrizio Smeraldi, Michael Defoin-Platel, Mansoor A. S. Saqi
2009 J jnl
J. Integr. Bioinform.
Mansoor A. S. Saqi, Richard J. B. Dobson, Preben Kraben, David A. Hodgson, David L. Wild
2009 J jnl
Briefings Bioinform.
Artem Lysenko, Matthew Morritt Hindle, Jan Taubert, Mansoor A. S. Saqi, Christopher J. Rawlings
2009 J jnl
J. Integr. Bioinform.
Richard J. B. Dobson, Patricia B. Munroe, Mark J. Caulfield, Mansoor A. S. Saqi
2008 conf
BIRD
Richard J. B. Dobson, Patricia B. Munroe, Charles A. Mein, Mark J. Caulfield, Mansoor A. S. Saqi
2006 J jnl
BMC Bioinform.
James A. Casbon, Gavin E. Crooks, Mansoor A. S. Saqi
2006 J jnl
J. Integr. Bioinform.
James A. Casbon, Mansoor A. S. Saqi
2006 J jnl
BMC Bioinform.
James A. Casbon, Mansoor A. S. Saqi
2006 J jnl
BMC Bioinform.
Richard J. B. Dobson, Patricia B. Munroe, Mark J. Caulfield, Mansoor A. S. Saqi
2005 J jnl
Nucleic Acids Res.
James A. Casbon, Mansoor A. S. Saqi
2004 J jnl
BMC Bioinform.
James A. Casbon, Mansoor A. S. Saqi
2003 B conf
IJCNN
Alberto Paccanaro, Chakra Chennubhotla, James A. Casbon, Mansoor A. S. Saqi
1999 J jnl
Bioinform.
Mansoor A. S. Saqi, David L. Wild, M. J. Hartshorn
1997 J jnl
Comput. Appl. Biosci.
Ross D. King, Mansoor A. S. Saqi, Roger A. Sayle, Michael J. E. Sternberg
1995 J jnl
Comput. Appl. Biosci.
Roger A. Sayle, Mansoor A. S. Saqi, M. Weir, Andrew Lyall
1994 J jnl
Comput. Appl. Biosci.
Mansoor A. S. Saqi, Roger A. Sayle
redb/extractors/decompiler/apk/smali_normalization.py
← Index redb/extractors/decompiler/apk/smali_normalization.py python
"""Semantic normalization of Dalvik/smali instructions.

Analogous to Binary Ninja's LLIL normalization: strips register allocation
noise and instruction encoding variants while preserving semantic operations.

Three normalization levels (most aggressive to most detailed):
  - 'category':    semantic category only (MOV, ALU, CALL, ...)
  - 'opcode':      base opcode, width-invariant (add, sub, invoke, ...)
  - 'opcode_api':  opcode category + API method/field references for
                   invoke/field/alloc instructions (default for MinHash)

References:
  - Smali+ 12-category reduction (Canfora et al.)
  - MOSDroid opcode family grouping
  - DroidSIFT/DroidSim API-sensitive similarity
"""

import re
from typing import List

# ---------------------------------------------------------------------------
# Dalvik opcode -> semantic category mapping
# ---------------------------------------------------------------------------
# Prefix-matched against instruction opcodes. Order matters for overlapping
# prefixes (longer/more-specific prefixes should come first in iteration,
# but since we use startswith and break on first match, we order by
# specificity within the list).

OPCODE_CATEGORIES = {
    # Arithmetic/logic
    "add": "ALU", "sub": "ALU", "mul": "ALU", "div": "ALU",
    "rem": "ALU", "and": "ALU", "or": "ALU", "xor": "ALU",
    "shl": "ALU", "shr": "ALU", "ushr": "ALU", "neg": "ALU",
    "not": "ALU",
    # Data movement
    "move": "MOV", "const": "CONST",
    # Memory access (field/array)
    "iget": "LOAD", "sget": "LOAD", "aget": "LOAD",
    "iput": "STORE", "sput": "STORE", "aput": "STORE",
    # Invocations
    "invoke": "CALL",
    # Control flow
    "if": "BRANCH", "goto": "JMP",
    "switch": "SWITCH",
    "return": "RET",
    # Object/type
    "new": "ALLOC", "check": "TYPE", "instance": "TYPE",
    # Array
    "fill": "ARR", "array": "ARR",
    # Comparison
    "cmpl": "CMP", "cmpg": "CMP", "cmp": "CMP",
    # Exception / synchronization
    "throw": "EXC", "monitor": "SYNC",
    # Conversion (int-to-long, float-to-int, etc.)
    "int-to": "CONV", "long-to": "CONV", "float-to": "CONV",
    "double-to": "CONV",
}

# Pre-compiled regexes for operand extraction
_METHOD_REF_RE = re.compile(r"(L[\w/$]+;->[\w<>]+\(.*?\)[\w/$;\[]*)")
_FIELD_REF_RE = re.compile(r"(L[\w/$]+;->[\w]+:[\w/$;\[]+)")
_CLASS_REF_RE = re.compile(r"(L[\w/$]+;)")
_CONST_STRING_RE = re.compile(r'^const-string(?:/jumbo)?\s')


def categorize_opcode(opcode: str) -> str:
    """Map a Dalvik opcode to its semantic category.

    Prefix-matched: 'add-int/2addr' matches 'add' -> 'ALU'.
    Returns 'OTHER' for unrecognized opcodes.
    """
    for prefix, cat in OPCODE_CATEGORIES.items():
        if opcode.startswith(prefix):
            return cat
    return "OTHER"


# Mapping from semantic categories to the ACFG feature vector indices
# used by Binary Ninja's build_block_features (cfg_features.py).
# This enables cross-platform ACFG feature comparison.
CATEGORY_TO_ACFG_INDEX = {
    "ALU": 0,       # CAT_ARITHMETIC
    "CONV": 0,      # arithmetic-adjacent
    "CMP": 4,       # CAT_COMPARISON
    "MOV": 2,       # CAT_TRANSFER
    "CONST": 2,     # transfer-adjacent (loading constants)
    "LOAD": 5,      # CAT_MEMORY
    "STORE": 5,     # CAT_MEMORY
    "CALL": 3,      # CAT_CALL
    "BRANCH": 1,    # CAT_LOGIC (conditional logic)
    "JMP": 1,       # CAT_LOGIC
    "SWITCH": 1,    # CAT_LOGIC
    "RET": 2,       # CAT_TRANSFER
    "ALLOC": 5,     # CAT_MEMORY (heap allocation)
    "TYPE": 6,      # CAT_OTHER
    "ARR": 5,       # CAT_MEMORY
    "EXC": 6,       # CAT_OTHER
    "SYNC": 6,      # CAT_OTHER
    "OTHER": 6,     # CAT_OTHER
}


def normalize_instruction(line: str, level: str = "opcode_api") -> str:
    """Normalize a single smali instruction line.

    Args:
        line: A single smali instruction (whitespace-stripped).
        level: Normalization level:
            'category'   - most aggressive: just semantic category
            'opcode'     - base opcode only, width/addressing-mode invariant
            'opcode_api' - category + API references for invoke/field/alloc
                          (default, best for MinHash similarity)

    Returns:
        Normalized instruction string, or empty string for non-instructions.
    """
    stripped = line.strip()
    if not stripped:
        return ""

    parts = stripped.split(None, 1)
    opcode = parts[0]
    operands = parts[1] if len(parts) > 1 else ""

    if level == "category":
        return categorize_opcode(opcode)

    if level == "opcode":
        # Strip type/width suffixes for invariance:
        # add-int, add-long, add-float -> 'add'
        # add-int/2addr -> 'add'
        base = re.split(r"[-/]", opcode)[0]
        return base

    if level == "opcode_api":
        # const-string: preserve string content (encrypted strings are a
        # key malware indicator)
        if _CONST_STRING_RE.match(stripped):
            # Extract the string literal
            str_match = re.search(r'"(.*)"', operands)
            if str_match:
                return f"CONST_STR \"{str_match.group(1)}\""
            return "CONST_STR"

        # invoke-*: preserve method reference
        if opcode.startswith("invoke"):
            ref = _METHOD_REF_RE.search(operands)
            if ref:
                return f"CALL {ref.group(1)}"
            return "CALL"

        # Field access: preserve field reference
        if opcode.startswith(("iget", "iput", "sget", "sput")):
            ref = _FIELD_REF_RE.search(operands)
            if ref:
                cat = "LOAD" if "get" in opcode else "STORE"
                return f"{cat} {ref.group(1)}"
            # Fallback: try space-separated format from androguard
            # e.g. "iget v0, p0, Lcom/Foo;->field Ljava/lang/String;"
            space_ref = re.search(
                r"(L[\w/$]+;->[\w]+)\s+([\w/$;\[]+)", operands
            )
            if space_ref:
                cat = "LOAD" if "get" in opcode else "STORE"
                return f"{cat} {space_ref.group(1)}:{space_ref.group(2)}"
            cat = "LOAD" if "get" in opcode else "STORE"
            return cat

        # new-instance: preserve allocated type
        if opcode.startswith("new-instance") or opcode == "new-array":
            ref = _CLASS_REF_RE.search(operands)
            if ref:
                return f"ALLOC {ref.group(1)}"
            return "ALLOC"

        # Everything else: just the category
        return categorize_opcode(opcode)

    # Unknown level: return raw opcode
    return opcode


def normalize_method_body(
    body: str, level: str = "opcode_api"
) -> List[str]:
    """Normalize all instructions in a smali method body.

    Filters out directives (.), labels (:), comments (#), and blank lines.
    Returns a list of normalized instruction strings.

    Args:
        body: Raw smali method body text.
        level: Normalization level (see normalize_instruction).

    Returns:
        List of normalized instruction strings (no empty strings).
    """
    normalized = []
    for line in body.split("\n"):
        stripped = line.strip()
        # Skip non-instructions
        if not stripped:
            continue
        if stripped.startswith((".",":", "#")):
            continue
        result = normalize_instruction(stripped, level)
        if result:
            normalized.append(result)
    return normalized