Vincent Poulain D'Andecy

54 papers A 5B 11Misc 1Journal 9Unranked 27
YearRankTypeTitle / Venue / Authors
2025 J jnl
Neurocomputing
Tri-Cong Pham, Mickaël Coustaty, Antoine Doucet, Aurélie Joseph, Vincent Poulain D'Andecy
2025 conf
ICDAR (3)
Tri-Cong Pham, Mickaël Coustaty, Aurélie Joseph, Gaspar Deloin, Vincent Poulain D'Andecy, Antoine Doucet
2025 J jnl
Trans. Mach. Learn. Res.
Marlon Tobaben, Mohamed Ali Souibgui, Rubèn Tito, Khanh Nguyen, Raouf Kerkouche, Kangsoo Jung, Joonas Jälkö, Lei Kang, Andrey Barsky, Vincent Poulain D'Andecy, Aurélie Joseph, Aashiq Muhamed, Kevin Kuo, Virginia Smith, Yusuke Yamasaki, Takumi Fukami, Kenta Niwa, Iifan Tyou, Hiro Ishii, Rio Yokota, Ragul N, Rintu Kutum, Josep Lladós, Ernest Valveny, Antti Honkela, Mario Fritz, Dimosthenis Karatzas
2025 conf
ICDAR (5)
Eliott Thomas, Mickaël Coustaty, Aurélie Joseph, Gaspar Deloin, Elodie Carel, Vincent Poulain D'Andecy, Jean-Marc Ogier
2025 J jnl
CoRR
Eliott Thomas, Mickaël Coustaty, Aurélie Joseph, Gaspar Deloin, Elodie Carel, Vincent Poulain D'Andecy, Jean-Marc Ogier
2025 conf
WACV (Workshops)
Eliott Thomas, Mickaël Coustaty, Aurélie Joseph, Gaspar Deloin, Elodie Carel, Vincent Poulain D'Andecy, Jean-Marc Ogier
2025 J jnl
CoRR
Eliott Thomas, Mickaël Coustaty, Aurélie Joseph, Gaspar Deloin, Elodie Carel, Vincent Poulain D'Andecy, Jean-Marc Ogier
2024 conf
ICDAR (6)
Ibrahim Souleiman Mahamoud, Mickaël Coustaty, Aurélie Joseph, Vincent Poulain D'Andecy, Jean-Marc Ogier
2024 conf
VISIGRAPP (4): VISAPP
Kais Rouis, Petra Gomez-Krämer, Mickaël Coustaty, Saddok Kebairi, Vincent Poulain D'Andecy
2024 conf
CORIA
Eliott Thomas, Dipendra Sharma Kafle, Ibrahim Souleiman Mahamoud, Aurélie Joseph, Mickaël Coustaty, Vincent Poulain D'Andecy
2024 conf
CORIA
Dipendra Sharma Kafle, Eliott Thomas, Mickaël Coustaty, Aurélie Joseph, Antoine Doucet, Vincent Poulain D'Andecy
2024 J jnl
CoRR
Marlon Tobaben, Mohamed Ali Souibgui, Rubèn Tito, Khanh Nguyen, Raouf Kerkouche, Kangsoo Jung, Joonas Jälkö, Lei Kang, Andrey Barsky, Vincent Poulain D'Andecy, Aurélie Joseph, Aashiq Muhamed, Kevin Kuo, Virginia Smith, Yusuke Yamasaki, Takumi Fukami, Kenta Niwa, Iifan Tyou, Hiro Ishii, Rio Yokota, Ragul N, Rintu Kutum, Josep Lladós, Ernest Valveny, Antti Honkela, Mario Fritz, Dimosthenis Karatzas
2024 conf
ICDAR (6)
Rubèn Tito, Khanh Nguyen, Marlon Tobaben, Raouf Kerkouche, Mohamed Ali Souibgui, Kangsoo Jung, Joonas Jälkö, Vincent Poulain D'Andecy, Aurélie Joseph, Lei Kang, Ernest Valveny, Antti Honkela, Mario Fritz, Dimosthenis Karatzas
2023 J jnl
Pattern Recognit. Lett.
Joris Voerman, Ibrahim Souleiman Mahamoud, Mickaël Coustaty, Aurélie Joseph, Vincent Poulain D'Andecy, Jean-Marc Ogier
2023 J jnl
CoRR
Ibrahim Souleiman Mahamoud, Mickaël Coustaty, Aurélie Joseph, Vincent Poulain D'Andecy, Jean-Marc Ogier
2023 conf
ICDAR Workshops (2)
Eliott Thomas, Dipendra Sharma Kafle, Ibrahim Souleiman Mahamoud, Aurélie Joseph, Mickaël Coustaty, Vincent Poulain D'Andecy
2023 conf
ICDAR (5)
Tri-Cong Pham, Mickaël Coustaty, Aurélie Joseph, Vincent Poulain D'Andecy, Muriel Visani, Nicolas Sidere
2023 conf
CORIA-TALN (4)
Beatriz Martínez Tornés, Théo Taburet, Emanuela Boros, Kais Rouis, Petra Gomez-Krämer, Nicolas Sidere, Antoine Doucet, Vincent Poulain D'Andecy
2023 conf
ICDAR Workshops (2)
Ibrahim Souleiman Mahamoud, Mickaël Coustaty, Aurélie Joseph, Vincent Poulain D'Andecy, Jean-Marc Ogier
2023 conf
ICDAR (3)
Beatriz Martínez Tornés, Théo Taburet, Emanuela Boros, Kais Rouis, Antoine Doucet, Petra Gomez-Krämer, Nicolas Sidere, Vincent Poulain D'Andecy
2023 conf
ICDAR Workshops (2)
Dipendra Sharma Kafle, Eliott Thomas, Mickaël Coustaty, Aurélie Joseph, Antoine Doucet, Vincent Poulain D'Andecy
2022 conf
ICPR Workshops (4)
Théo Taburet, Kais Rouis, Mickaël Coustaty, Petra Gomez-Krämer, Nicolas Sidère, Saddok Kebairi, Vincent Poulain D'Andecy
2022 B conf
DAS
Ibrahim Souleiman Mahamoud, Mickaël Coustaty, Aurélie Joseph, Vincent Poulain D'Andecy, Jean-Marc Ogier
2021 conf
EGC
Ibrahim Souleiman Mahamoud, Joris Voerman, Mickaël Coustaty, Aurélie Joseph, Vincent Poulain D'Andecy, Jean-Marc Ogier
2021 conf
ICDAR (3)
Ibrahim Souleiman Mahamoud, Joris Voerman, Mickaël Coustaty, Aurélie Joseph, Vincent Poulain D'Andecy, Jean-Marc Ogier
2021 conf
ICDAR Workshops (2)
Joris Voerman, Ibrahim Souleiman Mahamoud, Aurélie Joseph, Mickaël Coustaty, Vincent Poulain D'Andecy, Jean-Marc Ogier
2020 B conf
DAS
Joris Voerman, Aurélie Joseph, Mickaël Coustaty, Vincent Poulain D'Andecy, Jean-Marc Ogier
2020 J jnl
CoRR
Joris Voerman, Aurélie Joseph, Mickaël Coustaty, Vincent Poulain D'Andecy, Jean-Marc Ogier
2019 A conf
ICDAR
Vincent Poulain D'Andecy, Aurélie Joseph, Joaquín Cuenca, Jean-Marc Ogier
2019 conf
CICLing (1)
Beatriz Martínez Tornés, Emanuela Boros, Antoine Doucet, Petra Gomez-Krämer, Jean-Marc Ogier, Vincent Poulain D'Andecy
2018 conf
CICLing (1)
Chloé Artaud, Antoine Doucet, Vincent Poulain D'Andecy, Jean-Marc Ogier
2018 conf
CVAUI/IWCF/MIPPSNA@ICPR
Francisco Cruz, Nicolas Sidère, Mickaël Coustaty, Vincent Poulain D'Andecy, Jean-Marc Ogier
2018 B conf
DAS
Ahmed Hamdi, Mickaël Coustaty, Aurélie Joseph, Vincent Poulain D'Andecy, Antoine Doucet, Jean-Marc Ogier
2018 B conf
DAS
Vincent Poulain D'Andecy, Emmanuel Hartmann, Marçal Rusiñol
2018 B conf
ICPR
Chloé Artaud, Nicolas Sidere, Antoine Doucet, Jean-Marc Ogier, Vincent Poulain D'Andecy
2018 B conf
DAS
Vincent Poulain D'Andecy, Aurélie Joseph, Jean-Marc Ogier
2017 A conf
ICDAR
Francisco Cruz, Nicolas Sidere, Mickaël Coustaty, Vincent Poulain D'Andecy, Jean-Marc Ogier
2017 conf
WML@ICDAR
Ahmed Hamdi, Joris Voerman, Mickaël Coustaty, Aurélie Joseph, Vincent Poulain D'Andecy, Jean-Marc Ogier
2016 B conf
DAS
Nicolas Sidere, Jean-Yves Ramel, Sabine Barrat, Vincent Poulain D'Andecy, Saddok Kebairi
2016 B conf
DAS
Nihel Kooli, Abdel Belaïd, Aurélie Joseph, Vincent Poulain D'Andecy
2016 B conf
DAS
Dimosthenis Karatzas, Vincent Poulain D'Andecy, Marçal Rusiñol, Antonio Chica, Pere-Pau Vázquez Alcocer
2016 conf
CORIA-CIFED
Maroua Hammami, Pierre Héroux, Sébastien Adam, Vincent Poulain D'Andecy
2015 A conf
ICDAR
Elodie Carel, Jean-Christophe Burie, Vincent Courboulay, Jean-Marc Ogier, Vincent Poulain D'Andecy
2015 A conf
ICDAR
Maroua Hammami, Pierre Héroux, Sébastien Adam, Vincent Poulain D'Andecy
2014 B conf
ICFHR
Ahmad Montaser Awal, Abdel Belaïd, Vincent Poulain D'Andecy
2014 conf
CORIA-CIFED
Nicolas Sidere, Jean-Yves Ramel, Sabine Barrat, Vincent Poulain D'Andecy, Saddok Kebairi
2014 B conf
ICPR
Hani Daher, Mohamed-Rafik Bouguelia, Abdel Belaïd, Vincent Poulain D'Andecy
2014 conf
CORIA-CIFED
Haner Daher, Abdel Belaïd, Vincent Poulain D'Andecy
2013 A conf
ICDAR
Marçal Rusiñol, Tayeb Benkhelfallah, Vincent Poulain D'Andecy
2013 J jnl
CoRR
Abdel Belaïd, KC Santosh, Vincent Poulain D'Andecy
2013 Misc conf
MVA
Abdel Belaïd, KC Santosh, Vincent Poulain D'Andecy
2011 ch.
Learning Structure and Schemas from Documents
Abdel Belaïd, Vincent Poulain D'Andecy, Hatem Hamza, Yolande Belaïd
2011 conf
GREC
Marçal Rusiñol, Vincent Poulain D'Andecy, Dimosthenis Karatzas, Josep Lladós
1994 conf
ICPR (1)
Vincent Poulain D'Andecy, Jean Camillerapp, Ivan Leplumey
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