M. Iqbal Saripan

45 papers B 2C 2Journal 25Unranked 16
YearRankTypeTitle / Venue / Authors
2022 J jnl
Neural Networks
Dong Wen, Rou Li, Mengmeng Jiang, Jingjing Li, Yijun Liu, Xianling Dong, M. Iqbal Saripan, Haiqing Song, Wei Han, Yanhong Zhou
2022 C conf
ICCE
Noor Syamilah Zakaria, Neerusha Subarimaniam, M. Iqbal Saripan, Alyani Ismail
2020 J jnl
IEEE Access
Sadiq H. Abdulhussain, Syed Abdul Rahman Al-Haddad, M. Iqbal Saripan, Basheera M. Mahmmod, Aseel Hussien
2020 J jnl
IEEE Access
Siti Fairuz Mat Radzi, Muhammad Khalis Abdul Karim, M. Iqbal Saripan, Mohd Amiruddin Abd Rahman, Nurul Huda Osman, Entesar Zawam Dalah, Noramaliza Mohd Noor
2019 B conf
IJCNN
Sadiq H. Abdulhussain, Abd. Rahman Ramli, Basheera M. Mahmmod, M. Iqbal Saripan, S. A. R. Al-Haddad, Thar Baker, Wameedh Nazar Flayyih, Wissam A. Jassim
2019 J jnl
J. Math. Imaging Vis.
Sadiq H. Abdulhussain, Abd. Rahman Ramli, Basheera M. Mahmmod, M. Iqbal Saripan, S. A. R. Al-Haddad, Wissam A. Jassim
2019 conf
HAVE
Hafiz Rashidi Ramli, Norhisam Misron, M. Iqbal Saripan, Fernando Bello
2019 J jnl
Multim. Tools Appl.
Sadiq H. Abdulhussain, Abd. Rahman Ramli, Basheera M. Mahmmod, M. Iqbal Saripan, S. A. R. Al-Haddad, Wissam A. Jassim
2018 conf
AsiaHaptics
Hafiz Rashidi Ramli, Norhisam Misron, M. Iqbal Saripan, Fernando Bello
2018 J jnl
Entropy
Sadiq H. Abdulhussain, Abd. Rahman Ramli, M. Iqbal Saripan, Basheera M. Mahmmod, Syed Abdul Rahman Al-Haddad, Wissam A. Jassim
2017 J jnl
J. Digit. Imaging
Afsaneh Jalalian, Syamsiah Mashohor, Rozi Mahmud, Babak Karasfi, M. Iqbal Saripan, Abdul Rahman Ramli
2017 conf
ICSIPA
Farhad Goodarzi, Fakhrul Zaman Rokhani, M. Iqbal Saripan, Mohammad Hamiruce Marhaban
2016 J jnl
Int. J. Biom.
Zarina Mohd Noh, Abdul Rahman Ramli, M. Iqbal Saripan, Marsyita Hanafi
2016 conf
ISQED
Lalitha Sivaraj, Nurul Amziah Md Yunus, Mohd Nazim Mokhtar, Samsuzana Abd Aziz, Zurina Zainal Abidin, M. Iqbal Saripan, Fakhrul Zaman Rokhani
2015 J jnl
Evol. Syst.
Abbas M. Al-Ghaili, Khairulmizam Samsudin, M. Iqbal Saripan, Wan Azizun Wan Adnan
2015 J jnl
J. Comput. Sci.
Anas A. Abboud, Rahmita Wirza O. K. Rahmat, Suhaini B. Kadiman, Mohd Zamrin Dimon, Lili Nurliyana Abdullah, M. Iqbal Saripan, Hasan H. Khaleel
2015 conf
ICSIPA
Farhad Goodarzi, M. Iqbal Saripan
2014 J jnl
J. Comput. Sci.
Anas A. Abboud, Rahmita Wirza O. K. Rahmat, Suhaini B. Kadiman, Mohd Zamrin Dimon, Lili Nurliyana Abdullah, M. Iqbal Saripan, Hasan H. Khaleel
2014 J jnl
J. Medical Syst.
Omar Hussein Salman, Mohd Fadlee A. Rasid, M. Iqbal Saripan, Shamala K. Subramaniam
2014 J jnl
J. Inf. Process. Syst.
Zaher Hamid Al-Tairi, Rahmita Wirza O. K. Rahmat, M. Iqbal Saripan, Puteri Suhaiza Sulaiman
2013 conf
ICSIPA
Rabiu Habibu, M. Iqbal Saripan, Mohammad Hamiruce Marhaban, Syamsiah Mashohor
2013 J jnl
Int. J. Distributed Sens. Networks
Faraneh Zarafshan, Abbas Karimi, Syed Abdul Rahman Al-Haddad, M. Iqbal Saripan, Shamala Subramaniam
2013 conf
ICSIPA
S. F. Md Ali, Xianling Dong, A. S. Muhammad Noor, Fakhrul Zaman Rokhani, Shaiful J. Hashim, M. Iqbal Saripan
2013 conf
ICCSCE
M. H. Hesamian, Syamsiah Mashohor, M. Iqbal Saripan, Wan Azizun Wan Adnan
2013 conf
ICSIPA
Xianling Dong, Wira Hidayat Mohd Saad, Wan Azizun Wan Adnan, Suhairul Hashim, Nor Pai'za Mohd. Hassan, Abdul Jalil Nordin, M. Iqbal Saripan
2012 J jnl
EURASIP J. Adv. Signal Process.
Rabiu Habibu, M. Iqbal Saripan, Syamsiah Mashohor, Mohammad Hamiruce Marhaban
2012 conf
Asia International Conference on Modelling and Simulation
Farzan Khatib, Rozi Mahmud, Syamsiah Mashohor, M. Iqbal Saripan, Raja Syamsul Azmir Raja Abdullah
2012 conf
CICSyN
Farzan Khatib, Rozi Mahmud, Syamsiah Mashohor, M. Iqbal Saripan, Raja Syamsul Azmir Raja Abdullah
2012 B conf
PRICAI
Rabiu Habibu, Syamsiah Mashohor, Mohammad Hamiruce Marhaban, M. Iqbal Saripan
2011 conf
ICSIPA
Tung Li Qian, Suhaidi Shafie, M. Iqbal Saripan
2011 C conf
HIS
Hamid Shojanazeri, Wan Azizun Wan Adnan, Sharifah Mumtadzah Syed Ahmad, M. Iqbal Saripan
2011 conf
MIAD
Iman Avazpour, Raja Syamsul Azmir, Raja Abdullah, Abdul Jalil Nordin, M. Iqbal Saripan
2010 J jnl
Artif. Intell. Rev.
Alaa Khamees Al-Azzawi, M. Iqbal Saripan, Adznan Bin Jantan, Rahmita Wirza O. K. Rahmat
2010 J jnl
J. Circuits Syst. Comput.
M. A. Balafar, Abdul Rahman Ramli, M. Iqbal Saripan, Syamsiah Mashohor, Rozi Mahmud
2010 J jnl
IEICE Electron. Express
Omid Sojodishijani, Abdul Rahman Ramli, Vahid Rostami, Khairulmizam Samsudin, M. Iqbal Saripan
2010 J jnl
J. Circuits Syst. Comput.
M. A. Balafar, Abdul Rahman Ramli, M. Iqbal Saripan, Syamsiah Mashohor, Rozi Mahmud
2010 J jnl
Comput. Inf. Sci.
Zinah Rajab Hussein, Rahmita Wirza O. K. Rahmat, Lili Nurliyana Abdullah, M. Iqbal Saripan, Mohd Zamrin Dimon
2010 J jnl
Artif. Intell. Rev.
M. A. Balafar, Abdul Rahman Ramli, M. Iqbal Saripan, Syamsiah Mashohor
2009 J jnl
CoRR
Abbas Karimi, Faraneh Zarafshan, Adznan Bin Jantan, Abdul Rahman Ramli, M. Iqbal Saripan
2009 J jnl
CoRR
Samaneh Rastegari, M. Iqbal Saripan, Mohd Fadlee A. Rasid
2009 conf
IVIC
Mohd. Hafrizal Azmi, M. Iqbal Saripan, Raja Syamsul Azmir, Raja Abdullah
2008 conf
ICIC (3)
M. A. Balafar, Abdul Rahman Ramli, M. Iqbal Saripan, Rozi Mahmud, Syamsiah Mashohor
2008 conf
ICIC (3)
M. A. Balafar, Abdul Rahman Ramli, M. Iqbal Saripan, Rozi Mahmud, Syamsiah Mashohor
2008 J jnl
J. Commun. Networks
Mohammed Hayder Al-Mansoori, Nor Kamariah Noordin, M. Iqbal Saripan, Mohd Adzir Mahdi
2007 J jnl
IEEE Trans. Biomed. Eng.
M. Iqbal Saripan, Maria Petrou, Kevin Wells
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"