Xiangguo Cheng

58 papers B 3C 3Misc 1Journal 39Unranked 12
YearRankTypeTitle / Venue / Authors
2024 J jnl
IEEE Access
Lida Xu, Xiangguo Cheng, Weizhong Tian, Huanli Wang, Yan Zhang
2021 J jnl
Wirel. Commun. Mob. Comput.
Rui Zhang, Hui Xia, Chao Liu, Ruobing Jiang, Xiangguo Cheng
2021 conf
WASA (2)
Shu-shu Shao, Hui Xia, Rui Zhang, Xiangguo Cheng
2021 J jnl
Comput. Commun.
Jufu Cui, Hui Xia, Rui Zhang, Benxu Hu, Xiangguo Cheng
2020 J jnl
IEEE Internet Things J.
Hui Xia, Li Li, Xiangguo Cheng, Chao Liu, Tie Qiu
2020 J jnl
IEEE Access
Yizhe Li, Hui Xia, Rui Zhang, Benxu Hu, Xiangguo Cheng
2020 conf
WASA (2)
Rui Zhang, Hui Xia, Jufu Cui, Xiangguo Cheng
2020 J jnl
IEEE Trans. Netw. Sci. Eng.
Hui Xia, Fu Xiao, Sanshun Zhang, Xiangguo Cheng, Zhenkuan Pan
2020 J jnl
IEEE Access
Xiuqing Lu, Xiangguo Cheng
2020 J jnl
Mob. Inf. Syst.
Rui Zhang, Hui Xia, Shu-shu Shao, Hang Ren, Shuai Xu, Xiangguo Cheng
2020 J jnl
IEEE Access
Li Li, Jufu Cui, Rui Zhang, Hui Xia, Xiangguo Cheng
2020 J jnl
IEEE Access
Xuqi Wang, Xiangguo Cheng, Yu Xie
2020 J jnl
IEEE Internet Things J.
Hui Xia, Li Li, Xiangguo Cheng, Xiuzhen Cheng, Tie Qiu
2020 J jnl
IEEE Access
Rui Zhang, Hui Xia, Fei Chen, Li Li, Xiangguo Cheng
2020 J jnl
IEEE/ACM Trans. Netw.
Hui Xia, Rui Zhang, Xiangguo Cheng, Tie Qiu, Dapeng Oliver Wu
2019 conf
GLOBECOM Workshops
Xuqi Wang, Yu Xie, Xiangguo Cheng, Zhengtao Jiang
2019 J jnl
Comput. Networks
Hui Xia, Chun-qiang Hu, Fu Xiao, Xiangguo Cheng, Zhenkuan Pan
2019 J jnl
J. Cloud Comput.
Panpan Meng, Chengliang Tian, Xiangguo Cheng
2018 conf
WASA
Hui Xia, Benxia Li, Sanshun Zhang, Shiwen Wang, Xiangguo Cheng
2018 conf
IIKI
Sanshun Zhang, Shiwen Wang, Hui Xia, Xiangguo Cheng
2018 J jnl
Inf. Sci.
Jia Yu, Rong Hao, Hui Xia, Hanlin Zhang, Xiangguo Cheng, Fanyu Kong
2018 J jnl
Secur. Commun. Networks
Hui Xia, Sanshun Zhang, Benxia Li, Li Li, Xiangguo Cheng
2017 J jnl
J. Internet Serv. Inf. Secur.
Xiuxiu Jiang, Xinrui Ge, Jia Yu, Fanyu Kong, Xiangguo Cheng, Rong Hao
2016 J jnl
Wirel. Networks
Hui Xia, Jia Yu, Zhenkuan Pan, Xiangguo Cheng, Edwin Hsing-Mean Sha
2016 J jnl
Wirel. Pers. Commun.
Jia Yu, Hui Xia, Huawei Zhao, Rong Hao, Zhangjie Fu, Xiangguo Cheng
2015 conf
3PGCIC
Xiuxiu Jiang, Jia Yu, Fanyu Kong, Xiangguo Cheng, Rong Hao
2015 J jnl
IEEE Trans. Smart Grid
Feng Diao, Fangguo Zhang, Xiangguo Cheng
2014 J jnl
Frontiers Comput. Sci.
Huiyan Zhao, Jia Yu, Shaoxia Duan, Xiangguo Cheng, Rong Hao
2014 J jnl
Inf. Sci.
Jia Yu, Fanyu Kong, Xiangguo Cheng, Rong Hao, Guowen Li
2014 B conf
TrustCom
Hui Xia, Jia Yu, Zhiyong Zhang, Xiangguo Cheng, Zhenkuan Pan
2013 J jnl
J. Softw.
Xiangguo Cheng, Shaojie Zhou, Lifeng Guo, Jia Yu, Huiran Ma
2013 J jnl
Int. J. Secur. Networks
Jia Yu, Rong Hao, Xiangguo Cheng
2012 J jnl
J. Comput.
Xiangguo Cheng, Shaojie Zhou, Jia Yu, Xin Li, Huiran Ma
2012 J jnl
Fundam. Informaticae
Jia Yu, Fanyu Kong, Xiangguo Cheng, Rong Hao, Jianxi Fan
2012 J jnl
J. Syst. Softw.
Jia Yu, Fanyu Kong, Xiangguo Cheng, Rong Hao, Jianxi Fan
2012 J jnl
J. Inf. Sci. Eng.
Jia Yu, Fanyu Kong, Huawei Zhao, Xiangguo Cheng, Rong Hao, Xiang-Fa Guo
2011 J jnl
J. Comput.
Xiangguo Cheng, Chen Yang, Jia Yu
2011 J jnl
Fundam. Informaticae
Jia Yu, Fanyu Kong, Xiangguo Cheng, Rong Hao, Jianxi Fan
2011 J jnl
Inf. Sci.
Jia Yu, Rong Hao, Fanyu Kong, Xiangguo Cheng, Jianxi Fan, Yangkui Chen
2011 J jnl
J. Softw.
Xiangguo Cheng, Lifeng Guo, Chen Yang, Jia Yu
2011 J jnl
J. Inf. Sci. Eng.
Jia Yu, Fanyu Kong, Xiangguo Cheng, Rong Hao, Jianxi Fan
2011 conf
PAISI
Jia Yu, Fanyu Kong, Xiangguo Cheng, Rong Hao
2010 Misc conf
Inscrypt
Zhixiong Chen, Xiangguo Cheng, Chenhuang Wu
2010 J jnl
J. Networks
Jia Yu, Fanyu Kong, Xiangguo Cheng, Rong Hao, Yangkui Chen, Xuliang Li, Guowen Li
2009 J jnl
J. Softw.
Jia Yu, Fanyu Kong, Xiangguo Cheng, Rong Hao
2008 C conf
ProvSec
Jia Yu, Fanyu Kong, Xiangguo Cheng, Rong Hao, Guowen Li
2008 C conf
ProvSec
Jia Yu, Fanyu Kong, Xiangguo Cheng, Rong Hao, Guowen Li
2007 J jnl
Int. J. Netw. Secur.
Shi Cui, Pu Duan, Choong Wah Chan, Xiangguo Cheng
2006 C conf
ATC
Chen Yang, Xiangguo Cheng, Wenping Ma, Xinmei Wang
2006 J jnl
Int. J. Netw. Secur.
Xiangguo Cheng, Lifeng Guo, Xinmei Wang
2006 conf
AINA (1)
Jingmei Liu, Xiangguo Cheng, Xinmei Wang
2006 conf
AINA (1)
Shi Cui, Choong Wah Chan, Xiangguo Cheng
2005 B conf
AINA
Jingmei Liu, Baodian Wei, Xiangguo Cheng, Xinmei Wang
2005 B conf
AINA
Xiangguo Cheng, Jingmei Liu, Xinmei Wang
2005 J jnl
Appl. Math. Comput.
Jingmei Liu, Baodian Wei, Xiangguo Cheng, Xinmei Wang
2005 conf
CIS (2)
Jingmei Liu, Xiangguo Cheng, Xinmei Wang
2005 conf
CISC
Xiangguo Cheng, Huafei Zhu, Ying Qiu, Xinmei Wang
2005 conf
ICCSA (4)
Xiangguo Cheng, Jingmei Liu, Xinmei Wang
redb/extractors/decompiler/bninja/analysis/cfg-old.py
← Index redb/extractors/decompiler/bninja/analysis/cfg-old.py python
from collections import deque
from enum import Enum

from binaryninja.enums import (
    BranchType,
    InstructionTextTokenType,
)

# Support both package and standalone imports
try:
    from ..utils.hashes import calculate_md5, calculate_sha256
except ImportError:
    # Fallback to absolute imports (for multiprocessing spawned processes)
    from redb.extractors.decompiler.bninja.utils.hashes import calculate_md5, calculate_sha256


class CFGAnalysis:
    def __init__(self, function):
        self.function = function

    def determine_block_type(self, block) -> str:
        """Determine the type of a basic block."""
        # Check if it's a thunk function (usually just a jump or call)
        if len(block.disassembly_text) <= 2 and any(
            "jmp" in line.tokens[0].text.lower() for line in block.disassembly_text
        ):
            return "THUNK"

        # Check if it contains only data (no valid instructions)
        if all(not line.tokens for line in block.disassembly_text):
            return "DATA"

        # Default to code
        return "CODE"

    def extract_cyclomatic_complexity(self):
        """
        Cyclomatic complexity (McCabe’s metric) measures the number of linearly independent paths
        through a function’s control flow graph (CFG).
        The standard formula is:

            M = E - N + 2

        where:
            - E = number of edges in the CFG
            - N = number of nodes (basic blocks)
            - 2 accounts for the entry and exit nodes of a single connected graph
        """
        if self.function is None:
            return 0

        # number of basic blocks
        num_blocks = len(self.function.basic_blocks)
        # number of edges in the graph
        num_edges = sum(
            len(basic_block.outgoing_edges)
            for basic_block in self.function.basic_blocks
        )
        return num_edges - num_blocks + 2

    def extract_function_cfg(self):
        """Extract information about a function CFG and return it as a dictionary."""

        function = self.function
        function_data = {
            "function_address": self.function.start,
            "blocks": [],
            "measures": {
                "cyclomatic_complexity": self.extract_cyclomatic_complexity(),
            },
        }

        if self.function is None:
            return function_data

        # Get the map of the depth associated to every block
        depths = self.get_map_depth()

        # Get the map of the positions associated to every block
        id_maps = self.get_block_id_map()

        # Extract block data with graph structure information
        for block in function.basic_blocks:
            # dominators per every block translated
            dominators = sorted(self.extract_dominators(block, id_maps))

            # post dominators
            post_dominators = sorted(self.extract_post_dominators(block, id_maps))

            # Build block instructions string
            block_instructions = "\n".join(str(line) for line in block.disassembly_text)

            # Determine block type
            block_type = self.determine_block_type(block)

            # Extract successors directly from basic block
            successor_blocks = [edge.target.start for edge in block.outgoing_edges]
            # We ensure a canonical order and we sort the edges
            successor_blocks.sort()

            # Extract predecessors directly from basic block
            predecessor_blocks = [edge.source.start for edge in block.incoming_edges]
            # We ensure a canonical order and we sort the edges
            predecessor_blocks.sort()

            # Determine branch type from outgoing edges
            branch_type = self.determine_branch_type(block)

            instructions_count = len(block.disassembly_text)

            # Create block record
            block_json = {
                "function_address": self.function.start,
                "block_start_address": block.start,
                "block_end_address": block.end,
                "block_size": block.end - block.start,
                "instructions_count": instructions_count,
                "block_instructions_hash": calculate_sha256(block_instructions),
                "predecessor_blocks": predecessor_blocks,
                "successor_blocks": successor_blocks,
                "depth": depths[block.start],
                "position": id_maps[block.start],
                "branch_type": branch_type,
                "block_type": block_type,
                "flags": self.extract_block_flags(block),
                "dominators": dominators,
                "post_dominators": post_dominators,
            }
            function_data["blocks"].append(block_json)

        return function_data

    def extract_dominators(self, bb, id_maps):
        """Extract the dominators normalized"""
        dom_idx = [id_maps[d.start] for d in bb.dominators]
        return dom_idx

    def extract_post_dominators(self, bb, id_maps):
        """Extract the post-dominators normalized"""
        post_dom_idx = [id_maps[d.start] for d in bb.post_dominators]
        return post_dom_idx

    def determine_branch_type(self, block):
        """
        Determine the type of branch at the end of a basic block.
        This combines edge type information with instruction analysis.
        """
        # If no outgoing edges, it might be a return or terminal block
        if not block.outgoing_edges:
            # Check if the last instruction is a return
            for line in reversed(list(block.disassembly_text)):
                if line.tokens and any(
                    token.text.lower() in ["ret", "retn"] for token in line.tokens
                ):
                    return "RETURN"
            return "UNKNOWN"

        # Collect branch types from all outgoing edges
        branch_types = []
        for edge in block.outgoing_edges:
            edge_type = edge.type
            # Map edge type to our branch type enum
            if isinstance(edge_type, str):
                if edge_type == "IndirectCall":
                    branch_types.append("CALL")
                else:
                    branch_types.append("UNKNOWN")
            else:
                # Use our mapping for integer/enum values
                type_mapping = {
                    BranchType.UnconditionalBranch: "DIRECT",
                    BranchType.FalseBranch: "CONDITIONAL",
                    BranchType.TrueBranch: "CONDITIONAL",
                    BranchType.CallDestination: "CALL",
                    BranchType.FunctionReturn: "RETURN",
                    BranchType.SystemCall: "CALL",
                    BranchType.IndirectBranch: "INDIRECT",
                    BranchType.ExceptionBranch: "UNKNOWN",
                    BranchType.UnresolvedBranch: "UNKNOWN",
                    BranchType.UserDefinedBranch: "UNKNOWN",
                }
                branch_types.append(type_mapping.get(edge_type, "UNKNOWN"))

        # Determine overall branch type (prioritize CALL > RETURN > CONDITIONAL > DIRECT)
        if "CALL" in branch_types:
            return "CALL"
        elif "RETURN" in branch_types:
            return "RETURN"
        elif "CONDITIONAL" in branch_types:
            return "CONDITIONAL"
        elif "DIRECT" in branch_types:
            return "DIRECT"
        elif len(block.outgoing_edges) == 1:
            return "FALLTHROUGH"

        # If edge analysis was inconclusive, fall back to instruction analysis
        last_instr = None
        for line in reversed(list(block.disassembly_text)):
            if line.tokens:
                last_instr = line
                break

        if last_instr:
            mnemonic = None
            for token in last_instr.tokens:
                if token.type == InstructionTextTokenType.InstructionToken:
                    mnemonic = token.text.lower()
                    break

            if mnemonic:
                if mnemonic == "call":
                    return "CALL"
                elif mnemonic == "jmp":
                    return "DIRECT"
                elif mnemonic.startswith("j") and mnemonic != "jmp":
                    return "CONDITIONAL"
                elif mnemonic in ["ret", "retn"]:
                    return "RETURN"

        return "UNKNOWN"

    def get_map_depth(self):
        """
        Run a BFS on the basic blocks of the function to assign a depth to every block
        """

        depths = {}
        entry = self.function.get_basic_block_at(self.function.start)

        ### Simple BFS
        q = deque()
        q.append(entry)
        depths[entry.start] = 0

        while q:
            b = q.popleft()
            b_depth = depths[b.start]
            for edge in b.outgoing_edges:
                tgt = edge.target

                if tgt is None:
                    continue

                if tgt.start not in depths:
                    depths[tgt.start] = b_depth + 1
                    q.append(tgt)

        return depths

    def get_block_id_map(self):
        """
        Assign a unique, sequential ID to each basic block of the function using a BFS starting from the entry block.
        """

        id_map = {}
        entry = self.function.get_basic_block_at(self.function.start)

        q = deque()
        q.append(entry)

        current_id = 0
        id_map[entry.start] = current_id

        while q:
            b = q.popleft()
            for edge in b.outgoing_edges:
                tgt = edge.target

                if tgt is None:
                    continue

                if tgt.start not in id_map:
                    current_id += 1
                    id_map[tgt.start] = current_id
                    q.append(tgt)

        return id_map

    def extract_block_flags(self, block):
        """
        Get the flags for every basic block. Currently, we implemented these heuristics:
            - if a basic block is the entry node for a function
            - if a basic block is the exit block for a function
            - if a basic block is part of a natural loop
        """
        flags = []

        if block.start == self.function.start:
            flags.append(BlockFlags.EntryBlock.value)

        if any(edge.type == BranchType.FunctionReturn for edge in block.outgoing_edges):
            flags.append(BlockFlags.ExitBlock.value)

        # if this block is in its dominance frontier, then it's part of a natural loop
        if block in block.dominance_frontier:
            flags.append(BlockFlags.LoopBlock.value)

        return flags


class BlockFlags(Enum):
    # generally, the basic block identifying the entry point of the function
    EntryBlock = "EntryBlock"
    # any basic blocks that makes the control flow exiting from the current function
    ExitBlock = "ExitBlock"
    # any block is in a natural loop if it is in its own dominance frontier
    LoopBlock = "LoopBlock"


class BlockType(Enum):
    THUNK = "THUNK"
    DATA = "DATA"
    PADDING = "PADDING"
    CODE = "CODE"