Xi Ding

25 papers A 1B 1C 2Misc 1Journal 15Unranked 5
YearRankTypeTitle / Venue / Authors
2026 J jnl
Environ. Model. Softw.
Changhong Hu, Songtao Ai, Shoukat Ali Shah, Xi Ding, Yi Cai, Xinde Chu, Hanxiao Yuan, Runchuan Ouyang, Meng Cui, Christo Pimpirev
2026 J jnl
CoRR
Quoc-Huy Trinh, Xi Ding, Yang Liu, Zhenyue Qin, Xingjian Li, Gorkem Durak, Halil Ertugrul Aktas, Elif Keles, Ulas Bagci, Min Xu
2025 Misc conf
ICASSP
Xi Ding, Yifan He, Shuigeng Zhou, Guiyang Liu, Qi Zhou
2025 J jnl
IEICE Trans. Fundam. Electron. Commun. Comput. Sci.
Xi Ding, Xiang Li, Kunyu Liu, Yuguang Xu, Xiaofeng Wu, Peiyuan Wang, Zhuoqun Wang
2025 conf
WSA
Eduard A. Jorswieck, Xi Ding, Ignacio Santamaría
2025 J jnl
IEEE Trans. Artif. Intell.
Yifan He, Xi Ding, Yateng Tang, Jihong Guan, Shuigeng Zhou
2024 conf
QRS Companion
Xi Ding, Yi Zhu, Qiao Yu, Chongyang Huang
2024 A conf
EASE
Xi Ding, Yuan Huang, Xiangping Chen, Jing Bian
2024 J jnl
ACM Trans. Softw. Eng. Methodol.
Xi Ding, Rui Peng, Xiangping Chen, Yuan Huang, Jing Bian, Zibin Zheng
2024 conf
AIAI (Workshops)
Jesús Gutiérrez, Vladica Sark, Mert Özates, Anna Tzanakaki, Markos P. Anastasopoulos, Valerio Frascolla, Ioanna Mesogiti, Elina Theodoropoulou, George L. Lyberopoulos, Luis Díez, Ramón Agüero, Ignacio Santamaría, Padmanava Sen, Simon Pryor, Shahid Mumtaz, Salvatore Pontarelli, Federico Trombetti, Novella Bartolini, Eduard A. Jorswieck, Xi Ding, Navid Nikaein
2024 J jnl
ACM Trans. Softw. Eng. Methodol.
Hanyang Guo, Xiangping Chen, Yuan Huang, Yanlin Wang, Xi Ding, Zibin Zheng, Xiaocong Zhou, Hong-Ning Dai
2024 J jnl
ACM Trans. Knowl. Discov. Data
Yifan He, Yatao Bian, Xi Ding, Bingzhe Wu, Jihong Guan, Ji Zhang, Shuigeng Zhou
2023 J jnl
ACM Trans. Softw. Eng. Methodol.
Yuan Huang, Hanyang Guo, Xi Ding, Junhuai Shu, Xiangping Chen, Xiapu Luo, Zibin Zheng, Xiaocong Zhou
2021 conf
ICBDS
Hao Xu, Shihui Chen, Mengxue Yi, Ke Feng, Xi Ding, Yilin Liu, Yiyang Chen
2019 J jnl
Remote. Sens.
Songtao Ai, Xi Ding, Jiachun An, Guobiao Lin, Zemin Wang, Ming Yan
2019 J jnl
Remote. Sens.
Songtao Ai, Xi Ding, Florian Tolle, Zemin Wang, Xi Zhao
2019 C conf
APSEC
Zhangtao Chen, Jing Liu, Xi Ding, Miaomiao Zhang
2019 J jnl
Comput. Biol. Chem.
Li-Xia Zhu, Qin Liu, Ya-Fang Hua, Ning Yang, Xue-Gang Zhang, Xi Ding
2016 J jnl
Comput. Biol. Chem.
Jun Yao, Xiaojuan Zhao, Xi Ding
2015 conf
ACSC
Xi Ding, Lanshan Zhang, Ye Tian, Xiangyang Gong, Wendong Wang
2015 J jnl
Comput. Biol. Medicine
Beiji Zou, Shijian Liu, Shenghui Liao, Xi Ding, Ye Liang
2014 B conf
ICCCN
Yan Liu, Xin Xu, Xi Ding, Yong Cui
2012 J jnl
Comput. Methods Programs Biomed.
Shenghui Liao, Beiji Zou, Jian-Ping Geng, Jing-xiao Wang, Xi Ding
2011 J jnl
Comput. Methods Programs Biomed.
Jing-xiao Wang, Shenghui Liao, Xing-Hao Zhu, Ying Wang, Chong-xiang Ling, Xi Ding, Yi-Ming Fang, Xiu-hua Zhang
2008 C conf
CSCWD
Chang Feng Song, Bo Hu Li, Xudong Chai, Zhen Tang, Xi Ding
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