Kan Liu

41 papers A 1B 1Misc 1Journal 29Unranked 9
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Xianzhe Zheng, Zhengheng Wang, Ruiyan Ma, Rui Wang, Xiyu Wang, Rui Chen, Peng Zhang, Sicheng Pan, Zhangheng Huang, Chenxin Wu, Yi Zhang, Bo Cai, Kan Liu, Teng Ma, Yin Du, Dong Deng, Sai Wu, Guoyun Zhu, Wei Zhang, Feifei Li
2026 J jnl
ACM Trans. Design Autom. Electr. Syst.
Jiawen Cheng, Lingjie Li, Zhiqiang Liu, Kan Liu, Shan Shen, Zhenya Zhou, Wenjian Yu
2026 J jnl
BMC Medical Imaging
Yanping Su, Cunxue Pan, Hongfei Hu, Di Shen, Ruolei Ye, Chenhui Zhou, Mingzhen Chen, Minjiang Chen, Jian Chen, Kan Liu, Jiayi Shen, Shuiwei Xia, Min Xu, Lingchun Lv, Chenying Lu, Jiansong Ji
2026 A conf
EuroSys
Xiaoxiao Jiang, Suyi Li, Lingyun Yang, Tianyu Feng, Zhipeng Di, Weiyi Lu, Guoxuan Zhu, Xiu Lin, Kan Liu, Yinghao Yu, Tao Lan, Guodong Yang, Lin Qu, Liping Zhang, Wei Wang
2026 J jnl
CoRR
Jiarui Guo, Yuemeng Xu, Zongwei Lv, Yangyujia Wang, Xiaolin Wang, Kan Liu, Tao Lan, Lin Qu, Tong Yang
2026 J jnl
CoRR
Jiaji Zhang, Hailiang Zhao, Guoxuan Zhu, Ruichao Sun, Jiaju Wu, Xinkui Zhao, Hanlin Tang, Weiyi Lu, Kan Liu, Tao Lan, Lin Qu, Shuiguang Deng
2025 J jnl
Expert Syst. Appl.
Feng Yu, Zhiyong Xiao, Li Liu, Kan Liu, Man Tang, Minghua Jiang, Jinxuan Hou
2025 J jnl
IEEE Trans. Intell. Transp. Syst.
Kan Liu, Pengpeng Jiao, Weiqi Hong, Yue Chen
2025 J jnl
CoRR
Xiaohan Zhang, Kan Liu, Yangle Liu, Fengze Li, Jieming Ma, Yue Li
2025 J jnl
CoRR
Yangle Liu, Fengze Li, Kan Liu, Jieming Ma
2025 Misc conf
NSDI
Lingyun Yang, Yongchen Wang, Yinghao Yu, Qizhen Weng, Jianbo Dong, Kan Liu, Chi Zhang, Yanyi Zi, Hao Li, Zechao Zhang, Nan Wang, Yu Dong, Menglei Zheng, Lanlan Xi, Xiaowei Lu, Liang Ye, Guodong Yang, Binzhang Fu, Tao Lan, Liping Zhang, Lin Qu, Wei Wang
2025 J jnl
CoRR
Xiaoxiao Jiang, Suyi Li, Lingyun Yang, Tianyu Feng, Zhipeng Di, Weiyi Lu, Guoxuan Zhu, Xiu Lin, Kan Liu, Yinghao Yu, Tao Lan, Guodong Yang, Lin Qu, Liping Zhang, Wei Wang
2025 conf
USENIX ATC
Suyi Li, Lingyun Yang, Xiaoxiao Jiang, Hanfeng Lu, Dakai An, Zhipeng Di, Weiyi Lu, Jiawei Chen, Kan Liu, Yinghao Yu, Tao Lan, Guodong Yang, Lin Qu, Liping Zhang, Wei Wang
2025 B conf
IJCNN
Jiahao Qin, Kan Liu, Yuxiang Cai, Tianrui Ji, Feng Liu
2025 J jnl
CoRR
Xiwei Wu, Yueyang Feng, Xiaoyang Lu, Tianchuan Lin, Kan Liu, Zhiyi Wang, Shushu Wu, Lihan Xie, Chengxi Yang, Hongyi Zhong, Naijun Zhan, Zhenjiang Hu, Qinxiang Cao
2025 J jnl
CoRR
Chao Yi, Dian Chen, Gaoyang Guo, Jiakai Tang, Jian Wu, Jing Yu, Mao Zhang, Sunhao Dai, Wen Chen, Wenjun Yang, Yuning Jiang, Zhujin Gao, Bo Zheng, Chi Li, Dimin Wang, Dixuan Wang, Fan Li, Fan Zhang, Haibin Chen, Haozhuang Liu, Jialin Zhu, Jiamang Wang, Jiawei Wu, Jin Cui, Ju Huang, Kai Zhang, Kan Liu, Lang Tian, Liang Rao, Longbin Li, Lulu Zhao, Na He, Peiyang Wang, Qiqi Huang, Tao Luo, Wenbo Su, Xiaoxiao He, Xin Tong, Xu Chen, Xunke Xi, Yang Li, Yaxuan Wu, Yeqiu Yang, Yi Hu, Yinnan Song, Yuchen Li, Yujie Luo, Yujin Yuan, Yuliang Yan, Zhengyang Wang, Zhibo Xiao, Zhixin Ma, Zile Zhou, Ziqi Zhang
2024 J jnl
Neural Comput. Appl.
Kan Liu, Jiarui He, Yu Chen
2024 J jnl
Scientometrics
Kaiwen Shi, Kan Liu, Xinyan He
2024 J jnl
CoRR
Suyi Li, Lingyun Yang, Xiaoxiao Jiang, Hanfeng Lu, Zhipeng Di, Weiyi Lu, Jiawei Chen, Kan Liu, Yinghao Yu, Tao Lan, Guodong Yang, Lin Qu, Liping Zhang, Wei Wang
2023 J jnl
IEEE Trans. Parallel Distributed Syst.
Kan Liu, Wei Xue
2023 J jnl
CCF Trans. High Perform. Comput.
Kan Liu, Xinliang Wang, Wei Xue
2023 conf
ASP-DAC
Lingjie Li, Zhiqiang Liu, Kan Liu, Shan Shen, Wenjian Yu
2021 conf
ISSCC
Xugang Ke, Wen-Chuen Liu, Min Kyu Song, Jing Xue, Chen Zheng, Kan Liu, Yahui Leng, Min Chen
2021 conf
ICCSIP
Shiyu Chen, Yongjia Zhao, Xiaoyong Lei, Tao Qi, Kan Liu
2021 J jnl
Comput. Phys. Commun.
Honghui Shang, Xiaohui Duan, Fang Li, Libo Zhang, Zhiqian Xu, Kan Liu, Haiwen Luo, Yingrui Ji, Wenxuan Zhao, Wei Xue, Li Chen, Yunquan Zhang
2020 J jnl
IEEE Access
Tao Tao, Kan Liu, Li Wang, Haiying Wu
2020 J jnl
Database J. Biol. Databases Curation
Gleb Moisseyev, Kiyoul Park, Alix Cui, Daniel Freitas, Divith Rajagopal, Anji Reddy Konda, Madalayne Martin-Olenski, Mackenzie Mcham, Kan Liu, Qian Du, James C. Schnable, Etsuko N. Moriyama, Edgar B. Cahoon, Chi Zhang
2019 J jnl
IEEE Trans. Biomed. Eng.
Luman Qin, Wei Zhou, Shoukun Zhang, Boran Cheng, Shubin Wang, Songzhan Li, Yanqin Yang, Shengxiang Wang, Kan Liu, Nangang Zhang
2019 J jnl
IEEE Access
Kan Liu, Lu Chen
2019 J jnl
J. Vis.
Kan Liu, David Liu
2017 conf
EIT
Kan Liu, Qian Du, Guodong Ren, Bin Yu, Chi Zhang
2017 conf
BIBM
Kan Liu, Shangang Jia, Qian Du, Chi Zhang
2016 conf
CCIS
Kan Liu, Yi Sun, Dezheng Zhang
2016 J jnl
Remote. Sens.
Shenghui Fang, Wenchao Tang, Yi Peng, Yan Gong, Can Dai, Ruhui Chai, Kan Liu
2015 J jnl
J. Circuits Syst. Comput.
Kan Liu, Lenian He, Jianping Qiu
2015 conf
ICHI
Johnson Chao-Sheng Huang, Yin-Tzu Lin, Joseph Kwong-Leung Yu, Kan Liu, Yau-Hwang Kuo
2015 J jnl
IEEE Trans. Ind. Informatics
Zhao-Hua Liu, Xiao-Hua Li, Liang-Hong Wu, Shao-Wu Zhou, Kan Liu
2012 conf
BWCCA
Weifeng Lv, Kan Liu, Tongyu Zhu
2011 J jnl
Genom. Proteom. Bioinform.
Tongwu Zhang, Yingfeng Luo, Kan Liu, Linlin Pan, Bing Zhang, Jun Yu, Songnian Hu
2010 J jnl
Genom. Proteom. Bioinform.
Wanfei Liu, Dawei Huang, Kan Liu, Songnian Hu, Jun Yu, Gang Gao, Shuhui Song
2005 J jnl
J. Comput. Sci. Technol.
Yinglei Song, Jizhen Zhao, Chunmei Liu, Kan Liu, Russell L. Malmberg, Liming Cai
redb/extractors/decompiler/bninja/analysis/cfg_features.py
← Index redb/extractors/decompiler/bninja/analysis/cfg_features.py python
import struct
from collections import deque
from typing import Optional

import blake3
import mmh3


# ---------------------------------------------------------------------------
# Task 1.1: Core Graph Utilities
# ---------------------------------------------------------------------------

def bfs_order(successors: list[list[int]], n: int) -> list[int]:
    """
    BFS traversal from node 0 (entry block), returns node indices in visit order.
    Unreachable nodes appended at the end.
    """
    if n == 0:
        return []

    visited = set()
    order = []
    queue = deque([0])
    visited.add(0)

    while queue:
        idx = queue.popleft()
        order.append(idx)
        for target in successors[idx]:
            if target not in visited:
                visited.add(target)
                queue.append(target)

    # Append unreachable blocks (dead code)
    for i in range(n):
        if i not in visited:
            order.append(i)

    return order


def bfs_max_depth(successors: list[list[int]], n: int) -> int:
    """
    Maximum BFS depth from entry block (node 0).
    Replaces the per-block depth column with a single scalar.
    """
    if n == 0:
        return 0

    depth = {0: 0}
    max_d = 0
    queue = deque([0])

    while queue:
        node = queue.popleft()
        for s in successors[node]:
            if s not in depth:
                depth[s] = depth[node] + 1
                if depth[s] > max_d:
                    max_d = depth[s]
                queue.append(s)

    return max_d


# ---------------------------------------------------------------------------
# Task 1.2: Back-Edge Detection (Iterative DFS)
# ---------------------------------------------------------------------------

def count_back_edges(successors: list[list[int]], n: int) -> int:
    """
    Count natural loops via iterative DFS back-edge detection.
    A back edge is an edge to a GRAY (in-stack) node.

    Iterative to avoid stack overflow on functions with 1000+ blocks
    (common in obfuscated malware, VM dispatchers, unrolled loops).
    """
    if n == 0:
        return 0

    WHITE, GRAY, BLACK = 0, 1, 2
    color = [WHITE] * n
    back_edges = 0

    stack = [(0, iter(successors[0]))]
    color[0] = GRAY

    while stack:
        u, children = stack[-1]
        try:
            v = next(children)
            if color[v] == GRAY:
                back_edges += 1
            elif color[v] == WHITE:
                color[v] = GRAY
                stack.append((v, iter(successors[v])))
        except StopIteration:
            color[u] = BLACK
            stack.pop()

    return back_edges


# ---------------------------------------------------------------------------
# Task 1.3: Topology Hash
# ---------------------------------------------------------------------------

def compute_topology_hash(
    successors: list[list[int]],
    bfs: list[int],
    n: int,
) -> bytes:
    """
    BLAKE3 hash of BFS-ordered canonical adjacency.
    Pure graph shape — ignores all block content.
    Two functions with identical control flow structure produce identical hashes.

    Returns 16 bytes (128-bit).
    """
    if n == 0:
        return b'\x00' * 16

    # Remap: original index -> BFS position
    remap = {original: position for position, original in enumerate(bfs)}

    canonical = bytearray()
    for position in range(n):
        original_idx = bfs[position]
        remapped_succs = sorted(
            remap[s] for s in successors[original_idx] if s in remap
        )
        # Pack: node_index (2 bytes) + num_successors (1 byte) + successor indices (2 bytes each)
        canonical.extend(struct.pack('<HB', position, len(remapped_succs)))
        for s in remapped_succs:
            canonical.extend(struct.pack('<H', s))

    return blake3.blake3(bytes(canonical)).digest(length=16)


# ---------------------------------------------------------------------------
# Task 1.4: MD-Index (Top-Down and Bottom-Up)
# ---------------------------------------------------------------------------

def compute_md_index_topdown(
    successors: list[list[int]],
    predecessors: list[list[int]],
    bfs: list[int],
) -> int:
    """
    BinDiff-style top-down MD-index.
    Hash of (in_degree, out_degree) sequence in BFS order from entry.
    Returns UInt64.
    """
    if not bfs:
        return 0

    degree_bytes = bytearray()
    for idx in bfs:
        in_deg = min(len(predecessors[idx]), 255)
        out_deg = min(len(successors[idx]), 255)
        degree_bytes.extend(struct.pack('<BB', in_deg, out_deg))

    h = blake3.blake3(bytes(degree_bytes)).digest(length=8)
    return struct.unpack('<Q', h)[0]


def compute_md_index_bottomup(
    successors: list[list[int]],
    predecessors: list[list[int]],
    n: int,
) -> int:
    """
    Bottom-up MD-index: BFS from exit blocks (no successors),
    traversing edges in reverse.
    Returns UInt64.
    """
    if n == 0:
        return 0

    exits = [i for i in range(n) if len(successors[i]) == 0]
    if not exits:
        exits = [n - 1]  # Fallback: use last block

    visited = set(exits)
    order = []
    queue = deque(exits)

    while queue:
        idx = queue.popleft()
        order.append(idx)
        for pred in predecessors[idx]:
            if pred not in visited:
                visited.add(pred)
                queue.append(pred)

    # Append unreachable blocks
    for i in range(n):
        if i not in visited:
            order.append(i)

    degree_bytes = bytearray()
    for idx in order:
        in_deg = min(len(predecessors[idx]), 255)
        out_deg = min(len(successors[idx]), 255)
        degree_bytes.extend(struct.pack('<BB', in_deg, out_deg))

    h = blake3.blake3(bytes(degree_bytes)).digest(length=8)
    return struct.unpack('<Q', h)[0]


# ---------------------------------------------------------------------------
# Task 1.5: Prime Product
# ---------------------------------------------------------------------------

# Small primes assigned to LLIL opcode categories.
# Keys are the integer values of binaryninja.LowLevelILOperation enum members.
# We use integer keys so this module doesn't import binaryninja.
#
# Mapping rationale: same operation class -> same prime.
# Using LLIL (not native asm) makes this architecture-independent.
#
# Populated at import time by cfg.py using the real LowLevelILOperation enum values.
# Unknown ops map to prime 1 (identity element) in compute_prime_product().
LLIL_OP_PRIMES: dict[int, int] = {}


def compute_prime_product(llil_operations: list[int]) -> int:
    """
    Product of small primes assigned to each LLIL opcode.
    Position-independent: block reordering doesn't change the result.
    Mod 2^64 for fixed-size storage.

    Args:
        llil_operations: flat list of LLIL operation enum integer values
                         for all instructions in the function.
    Returns:
        UInt64 prime product, or 0 if no instructions.
    """
    if not llil_operations:
        return 0

    product = 1
    for op in llil_operations:
        prime = LLIL_OP_PRIMES.get(op, 1)
        product = (product * prime) % (2**64)

    return product


# ---------------------------------------------------------------------------
# Task 1.6: ACFG Block Features
# ---------------------------------------------------------------------------

# Instruction category indices for ACFG feature vectors
CAT_ARITHMETIC = 0
CAT_LOGIC = 1
CAT_TRANSFER = 2
CAT_CALL = 3
CAT_COMPARISON = 4
CAT_MEMORY = 5
CAT_OTHER = 6

# Maps LLIL operation integer values to category indices.
# Populated at import time by cfg.py using the real LowLevelILOperation enum.
LLIL_OP_CATEGORIES: dict[int, int] = {}


def build_block_features(
    block_llil_ops: list[list[int]],
    successors: list[list[int]],
    n: int,
) -> list[list[int]]:
    """
    Extract Gemini-style ACFG features per block.

    Args:
        block_llil_ops: per-block list of LLIL operation integer values.
                        block_llil_ops[i] is the list of ops for block i.
                        Empty list if LLIL unavailable for that block.
        successors: index-based adjacency list.
        n: number of blocks.

    Returns:
        List of [instr_count, arithmetic, logic, transfer, call, comparison,
                 memory, successor_count] per block. All values capped at 65535.
    """
    features = []
    for i in range(n):
        cats = [0, 0, 0, 0, 0, 0, 0]
        ops = block_llil_ops[i] if i < len(block_llil_ops) else []
        for op in ops:
            cat = LLIL_OP_CATEGORIES.get(op, CAT_OTHER)
            cats[cat] += 1

        instr_count = len(ops)
        features.append([
            min(instr_count, 65535),
            min(cats[CAT_ARITHMETIC], 65535),
            min(cats[CAT_LOGIC], 65535),
            min(cats[CAT_TRANSFER], 65535),
            min(cats[CAT_CALL], 65535),
            min(cats[CAT_COMPARISON], 65535),
            min(cats[CAT_MEMORY], 65535),
            min(len(successors[i]), 65535),
        ])

    return features


# ---------------------------------------------------------------------------
# Task 1.7: CFG Feature TLSH
# ---------------------------------------------------------------------------

def compute_cfg_feature_tlsh(
    bb_features: list[list[int]],
    bfs: list[int],
) -> Optional[str]:
    """
    TLSH hash of BFS-ordered per-block feature vectors.
    Captures both structure (BFS ordering) and instruction distribution.

    Returns TLSH hex string or None if too few bytes for TLSH (< 50).
    """
    import tlsh as _tlsh

    feature_bytes = bytearray()
    for idx in bfs:
        feats = bb_features[idx]
        feature_bytes.extend(struct.pack(
            '<HBBBBBBB',
            min(feats[0], 65535),
            min(feats[1], 255),
            min(feats[2], 255),
            min(feats[3], 255),
            min(feats[4], 255),
            min(feats[5], 255),
            min(feats[6], 255),
            min(feats[7], 255),
        ))

    if len(feature_bytes) < 50:
        return None

    try:
        h = _tlsh.hash(bytes(feature_bytes))
        return h if h and h != 'TNULL' else None
    except Exception:
        return None


# ---------------------------------------------------------------------------
# Task 1.8: WL-MinHash
# ---------------------------------------------------------------------------

# Pre-computed seeds for MinHash permutations.
NUM_WL_MINHASH_PERMS = 128
_WL_MINHASH_SEEDS = list(range(NUM_WL_MINHASH_PERMS))  # Seeds 0..127


def compute_wl_minhash(
    successors: list[list[int]],
    predecessors: list[list[int]],
    bb_features: list[list[int]],
    n: int,
    iterations: int = 3,
) -> list[int]:
    """
    Weisfeiler-Leman MinHash for fuzzy topology similarity.

    Initial labels: mmh3 hash of per-block ACFG feature tuple (content-aware).
    WL refinement: incorporate sorted neighbor labels at each iteration.
    MinHash: 128-permutation signature over shingle set.

    Returns list of 128 uint8 values, or [255]*128 sentinel for empty functions.
    """
    if n == 0:
        return [255] * NUM_WL_MINHASH_PERMS

    # Initial labels: hash of instruction category tuple per block
    labels = []
    for i in range(n):
        feats = bb_features[i] if i < len(bb_features) else [0] * 8
        # mmh3 with seed=0 for initial labels
        label = mmh3.hash(str(tuple(feats)), 0) & 0xFFFFFFFF
        labels.append(label)

    # Collect shingles: (iteration, label) pairs as strings for mmh3
    shingles: set[str] = set()

    # Iteration 0: individual block labels
    for label in labels:
        shingles.add(f"0:{label}")

    # WL iterations: refine labels by neighborhood aggregation
    for iteration in range(1, iterations + 1):
        new_labels = []
        for i in range(n):
            succ_labels = tuple(sorted(labels[s] for s in successors[i]))
            pred_labels = tuple(sorted(labels[p] for p in predecessors[i]))
            composite = f"{labels[i]}|{succ_labels}|{pred_labels}"
            new_label = mmh3.hash(composite, 0) & 0xFFFFFFFF
            new_labels.append(new_label)
            shingles.add(f"{iteration}:{new_label}")
        labels = new_labels

    if not shingles:
        return [255] * NUM_WL_MINHASH_PERMS

    # Compute MinHash signature using mmh3 with different seeds
    shingle_list = list(shingles)
    signature = []
    for seed in _WL_MINHASH_SEEDS:
        min_val = 0xFFFFFFFF
        for s in shingle_list:
            h = mmh3.hash(s, seed) & 0xFFFFFFFF
            if h < min_val:
                min_val = h
        # Compress to uint8 for storage
        signature.append(min_val & 0xFF)

    return signature


# ---------------------------------------------------------------------------
# Task 1.9: Packed Adjacency
# ---------------------------------------------------------------------------

def pack_adjacency(successors: list[list[int]]) -> list[int]:
    """
    Pack CFG edges as Array(UInt32).
    Each UInt32 = (source_index << 16) | target_index.
    Supports up to 65,535 blocks per function.
    """
    edges = []
    for src, targets in enumerate(successors):
        for tgt in targets:
            if src < 65536 and tgt < 65536:
                edges.append((src << 16) | tgt)
    return edges