Cao Truong Tran

32 papers A 3B 4C 1Journal 7Unranked 16
YearRankTypeTitle / Venue / Authors
2024 conf
RIVF
Xuan-Cong Pham, Trung-Nguyen Hoang, Viet-Binh Do, Cao Truong Tran
2024 J jnl
Evol. Intell.
Xuan Hung Nguyen, Cao Truong Tran, Lam Thu Bui
2024 conf
RIVF
Nguyen Thi Lan, Cao Truong Tran, Nguyen Hai Dang, Tran Thi Toi
2024 J jnl
Evol. Intell.
Cao Truong Tran, Binh P. Nguyen
2023 conf
ICIIT
Hien Nguyen Thi, Thi-Thu-Hong Phan, Cao Truong Tran
2022 conf
RIVF
Cao Truong Tran
2022 conf
RIVF
Cao Truong Tran
2021 conf
KSE
Dinh Tan Nguyen, Cao Truong Tran, Trung Thanh Nguyen, Cao Bao Hoang, Van Phu Luu, Ba Ngoc Nguyen, Pou Ian Cheong
2021 conf
KSE
Cao Truong Tran, Dinh Tan Nguyen, Ho Tan Hoang
2021 conf
RIVF
Hai-Hong Phan, Trung Tin Nguyen, Huu Phuc Ngo, Huu-Nhan Nguyen, Do Minh Hieu, Cao Truong Tran, Bao Ngoc Vi
2021 conf
RIVF
Bao Ngoc Vi, Dinh Tan Nguyen, Cao Truong Tran, Huu Phuc Ngo, Chi Cong Nguyen, Hai-Hong Phan
2020 J jnl
Evol. Intell.
Xuan Hung Nguyen, Lam Thu Bui, Cao Truong Tran
2019 conf
KSE
Xuan Hung Nguyen, Lam Thu Bui, Cao Truong Tran
2019 conf
KSE
Bao Ngoc Vi, Huu Noi Nguyen, Ngoc Tran Nguyen, Cao Truong Tran
2019 conf
SoICT
Xuan Hung Nguyen, Lam Thu Bui, Cao Truong Tran
2019 B conf
CEC
Will Pearson, Cao Truong Tran, Mengjie Zhang, Bing Xue
2019 J jnl
Comput. Methods Programs Biomed.
Binh P. Nguyen, Hung N. Pham, Hop Tran, Nhung Nghiem, Quang H. Nguyen, Trang T. T. Do, Cao Truong Tran, Colin R. Simpson
2018 J jnl
Knowl. Based Syst.
Cao Truong Tran, Mengjie Zhang, Peter Andreae, Bing Xue, Lam Thu Bui
2018
Cao Truong Tran
2018 conf
Australasian Conference on Artificial Intelligence
Cao Truong Tran, Mengjie Zhang, Bing Xue, Peter Andreae
2018 J jnl
Appl. Soft Comput.
Cao Truong Tran, Mengjie Zhang, Peter Andreae, Bing Xue, Lam Thu Bui
2017 conf
EvoApplications (1)
Cao Truong Tran, Mengjie Zhang, Peter Andreae, Bing Xue
2017 A conf
GECCO
Cao Truong Tran, Mengjie Zhang, Peter Andreae, Bing Xue
2017 A conf
GECCO
Cao Truong Tran, Mengjie Zhang, Peter Andreae, Bing Xue
2016 B conf
EuroGP
Cao Truong Tran, Mengjie Zhang, Peter Andreae
2016 conf
EvoApplications (1)
Cao Truong Tran, Mengjie Zhang, Peter Andreae, Bing Xue
2016 conf
GECCO (Companion)
Cao Truong Tran, Mengjie Zhang, Peter Andreae, Bing Xue
2016 B conf
CEC
Cao Truong Tran, Mengjie Zhang, Peter Andreae
2016 J jnl
Evol. Intell.
Cao Truong Tran, Mengjie Zhang, Peter Andreae, Bing Xue
2016 C conf
IES
Cao Truong Tran, Mengjie Zhang, Peter Andreae, Bing Xue, Lam Thu Bui
2015 B conf
CEC
Cao Truong Tran, Peter Andreae, Mengjie Zhang
2015 A conf
GECCO
Cao Truong Tran, Mengjie Zhang, Peter Andreae
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