Weichao Yang

26 papers A* 1C 2Journal 13Unranked 10
YearRankTypeTitle / Venue / Authors
2025 conf
VTC2025-Spring
Jiawei Li, Hongyan Wang, Mingyang Wang, Dawei Wang, Weichao Yang, Li Li, Yi Jin, Hongbo Zhao
2025 J jnl
IEEE Trans. Netw. Sci. Eng.
Dawei Wang, Zijun Wang, Weichao Yang, Hongbo Zhao, Yixin He, Li Li, Zhongxiang Wei, Fuhui Zhou
2025 J jnl
IEEE Internet Things J.
Dawei Wang, Tong Liu, Li Li, Weichao Yang, Yi Jin, Hongbo Zhao, Yixin He, Ruonan Zhang
2025 J jnl
IEEE Access
Weichao Yang
2025 J jnl
IEEE Trans. Wirel. Commun.
Dawei Wang, Zijun Wang, Hongbo Zhao, Fuhui Zhou, Osama Alfarraj, Weichao Yang, Shahid Mumtaz, Victor C. M. Leung
2025 J jnl
Stat. Comput.
Xu Guo, Hongwei Shi, Weichao Yang, Yiyuan Qian, Niwen Zhou
2024 C conf
IGARSS
Jixiang Fu, Weichao Yang, Min Xue, Zhixin Wu, Yang Lan, Mengdao Xing, Hongmeng Chen, Jun Li
2024 J jnl
IEEE Trans. Geosci. Remote. Sens.
Xi Yang, Sheng Zhang, Songsong Duan, Weichao Yang
2024 C conf
CSCWD
Juanru Zhang, Weichao Yang, Yinghui Zhang, Hao Zheng, Tiankui Zhang
2024 J jnl
Sensors
Zhongjun Li, Shuang Tian, Jiaxin Tang, Weichao Yang, Tao Hong, Huacheng Zhu
2024 A* conf
NeurIPS
Weichao Yang, Hongwei Shi, Xu Guo, Changliang Zou
2024 J jnl
Comput. Stat. Data Anal.
Weichao Yang, Xu Guo, Lixing Zhu
2024 J jnl
IEEE Trans. Geosci. Remote. Sens.
Xi Yang, Sheng Zhang, Weichao Yang
2023 J jnl
PeerJ Comput. Sci.
Huaqun Chen, Weichao Yang, Xie Tang, Minghui Yang, Fangwei Huang, Xingao Zhu
2022 conf
6GN (2)
Ziqi Sun, Weichao Yang, Yifan Ping, Ruofei Ma, Gongliang Liu
2022 conf
ICSEB
Weichao Yang, Hanning Li, Yang Li, Yu Zou, Haitao Zhao
2022 conf
6GN (1)
Ziqi Sun, Shengliang Fang, Weichao Yang, Gongliang Liu, Ruofei Ma
2022 conf
6GN (2)
Weichen Zhu, Weichao Yang, Gongliang Liu
2019 conf
WISATS (1)
Weichao Yang, Yu Du
2018 conf
RFID-TA
Yunxiu Wang, Yan Liu, Wenhui Zou, Yusong Hu, Weichao Yang
2018 J jnl
IEEE Trans. Ind. Informatics
Xinan Yuan, Wei Li, Guoming Chen, Xiaokang Yin, Weichao Yang, Jiuhao Ge
2018 J jnl
计算机科学
Chendong Wang, Yuanbo Guo, Shuaihui Zhen, Weichao Yang
2013 J jnl
Wirel. Pers. Commun.
Chunhui Zhao, Weichao Yang
2008 conf
ICNC (1)
Zhong Zhang, Weichao Yang, Qun Ding
2008 conf
ROBIO
Bo Song, Yong Yu, Weichao Yang, YunJian Ge
2007 conf
ROBIO
Xiaohong Deng, Weichao Yang, Huanghuan Shen, Yong Yu, YunJian Ge, Jian Sun
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