Ijaz Ahmed

51 papers A* 1B 1C 1Journal 37Unranked 10
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE Access
Mohammed Saber Eltohamy, Muhayya Saad Muhayya Aldawsari, Amir Raouf Adly Sadek, Hossam Youssef Abdel-Hamid Hegazy, Ijaz Ahmed, Theyab R. Alsenani, Yunsu Kim, Mohamed Mostafa Ramadan Ahmed
2026 J jnl
Commun. Nonlinear Sci. Numer. Simul.
Sami Ullah, Fatima Tahir, Muhammad Rehan, Ijaz Ahmed, Muhammad Waqas Khalid
2026 J jnl
Veh. Commun.
Paghunda Roheela Ali, Waqas Ahmed, Muhammad Rehan, Ijaz Ahmed, Muhammad Waqas Khalid
2026 J jnl
IEEE Trans. Cybern.
Mahrukh, Muhammad Rehan, Abdul Basit, Ijaz Ahmed, Choon Ki Ahn, Mohammed Chadli
2025 J jnl
Comput. Electr. Eng.
Ijaz Ahmed, Muhammad Adnan, Waqas Hassan
2025 J jnl
IEEE Commun. Lett.
Javeria Mumtaz, Abdul Basit, Muhammad Tufail, Muhammad Rehan, Ijaz Ahmed, Muhammad Waqas Khalid
2025 J jnl
J. Frankl. Inst.
Noman Liaqat, Qaisar Abbas Naqvi, Qurratulain Minhas, Muhammad Rehan, Ijaz Ahmed, Muhammad Khalid
2025 J jnl
Neural Comput. Appl.
Hasnain Ahmad, Muhammad Majid Gulzar, Ghulam Mustafa, Abdul Qayyum Khan, Salman Habib, Ijaz Ahmed
2025 J jnl
Soc. Netw. Anal. Min.
Hasnain Ahmad, Muhammad Majid Gulzar, Ijaz Ahmed, Muhammad Khalid
2025 J jnl
Artif. Intell. Rev.
Hasnain Ahmad, Ghulam Mustafa, Muhammad Majid Gulzar, Ijaz Ahmed, Muhammad Waqas Khalid
2025 J jnl
IEEE Trans. Netw. Sci. Eng.
Zarar Ahmed Malik, Muhammad Rehan, Waqas Ahmed, Ijaz Ahmed, Choon Ki Ahn
2025 J jnl
Computing
Ijaz Ahmed, Miswar Akhtar Syed, Muhammad Maaruf, Muhammad Khalid
2025 J jnl
IEEE Trans Autom. Sci. Eng.
Musawir Hussain, Fatima Tahir, Muhammad Rehan, Choon Ki Ahn, Ijaz Ahmed, Muhammad Waqas Khalid
2025 J jnl
Comput. Electr. Eng.
Muhammad Adnan, Muhammad Sajid Iqbal, Sadia Jabeen Siddiqi, Ijaz Ahmed, Anwar Shah, Inam Ullah, Muhammad Tariq
2025 J jnl
IEEE Access
Ahmed Babiker, Sulaiman S. Ahmad, Ijaz Ahmed, Muhammad Waqas Khalid, Mohammad A. Abido, Fahad Saleh Al-Ismail
2025 J jnl
Math. Comput. Simul.
Sajida Manzoor, Muhammad Rehan, Ijaz Ahmed
2024 conf
ICIT
Ijaz Ahmed, Abdul Basit, Muhammad Rehan, Amjad Ali, Muhammad Maaruf, Muhammad Khalid
2024 J jnl
Internet Things
Hasnain Ahmad, Muhammad Majid Gulzar, Saddam Aziz, Salman Habib, Ijaz Ahmed
2024 J jnl
IEEE Access
Muhammad Mamoon, Muhammad Rehan, Ghulam Mustafa, Naeem Iqbal, Ijaz Ahmed, Muhammad Waqas Khalid
2024 J jnl
IEEE Access
Arsalan Alam, Amena Ejaz Aziz, Abdul Basit, Ijaz Ahmed, Ali Arshad Nasir, Muhammad Waqas Khalid
2024 conf
ICIT
Faizan E. Mustafa, Ijaz Ahmed, Muhammad Maaruf, Muhammad Waqas Khalid
2024 conf
ICIT
Muhammad Moin, Muhammad Rehan, Ijaz Ahmed, Amjad Ali, Muhammad Khalid
2024 J jnl
IEEE Trans. Netw. Sci. Eng.
Abdul Basit, Muhammad Tufail, Muhammad Rehan, Waqas Ahmed, Ayman Radwan, Ijaz Ahmed
2024 J jnl
Expert Syst. Appl.
Noor ul Huda, Ijaz Ahmed, Muhammad Adnan, Mansoor Ali, Faisal Naeem
2024 J jnl
Comput. Electr. Eng.
Muhammad Adnan, Ijaz Ahmed, Sajid Iqbal, Muhammad Rayyan Fazal, Sadia Jabeen Siddiqi, Muhammad Tariq
2024 J jnl
Comput. Electr. Eng.
Muhammad Adnan, Ijaz Ahmed, Sajid Iqbal
2023 J jnl
IEEE Access
Ijaz Ahmed, Muhammad Rehan, Abdul Basit, Muhammad Tufail, Keum-Shik Hong
2023 J jnl
IEEE Trans. Netw. Sci. Eng.
Ijaz Ahmed, Muhammad Rehan, Naeem Iqbal, Choon Ki Ahn
2023 J jnl
Int. J. Crit. Infrastructure Prot.
Faizan E. Mustafa, Ijaz Ahmed, Abdul Basit, Um-E.-Habiba Alvi, Saddam Hussain Malik, Atif Mahmood, Paghunda Roheela Ali
2023 J jnl
IEEE Access
Faizan E. Mustafa, Abdul Qayyum Khan, Abdus Samee, Ijaz Ahmed, Muhammad Abid, Mohammad M. Alqahtani, Muhammad Waqas Khalid
2023 J jnl
IEEE Access
Manzoor Ahmad, Nadeem Javaid, Iftikhar Azim Niaz, Ijaz Ahmed, Muhammad Adnan Hashmi
2023 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Abdul Basit, Muhammad Tufail, Muhammad Rehan, Muhammad Riaz, Ijaz Ahmed
2023 J jnl
IEEE Access
Ijaz Ahmed, Muhammad Rehan, Abdul Basit, Muhammad Tufail, Keum-Shik Hong
2023 J jnl
IEEE Access
Muhammad Adnan, Yazeed Ghadi, Ijaz Ahmed, Mansoor Ali
2022 conf
ASCC
Ijaz Ahmed, Muhammad Rehan, Keum-Shik Hong, Abdul Basit
2022 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Ijaz Ahmed, Muhammad Rehan, Naeem Iqbal
2022 J jnl
Soft Comput.
Um-E.-Habiba Alvi, Waqas Ahmed, Muhammad Rehan, Shakeel Ahmed, Rizwan Ahmad, Ijaz Ahmed
2022 conf
ASCC
Abdul Basit, Muhammad Tufail, Keum-Shik Hong, Muhammad Rehan, Ijaz Ahmed
2022 conf
ASCC
Ijaz Ahmed, Muhammad Rehan, Keum-Shik Hong, Abdul Basit
2022 J jnl
IEEE Access
Qazi Mudassar Ilyas, Muneer Ahmad, Noor Zaman, Majed A. Alshamari, Ijaz Ahmed
2020 conf
ICCHP (2)
Hemanshu Bhargav, Ijaz Ahmed, Margot Whitfield, Raaga Shankar, Mauricio Meza, Deborah I. Fels
2019 A* conf
ASE
Ayesha Sadiq, Li Li, Yuan-Fang Li, Ijaz Ahmed, Sea Ling
2019 J jnl
CoRR
Ayesha Sadiq, Yuan-Fang Li, Sea Ling, Li Li, Ijaz Ahmed
2018 conf
ICACS
Ijaz Ahmed, Néstor Cataño
2018 conf
ICACS
Ijaz Ahmed, Ayesha Sadiq, Muhammad Atif, Mudasser Naseer, Muhammad Adnan
2016 B conf
ICECCS
Ayesha Sadiq, Yuan-Fang Li, Sea Ling, Ijaz Ahmed
2014 J jnl
Sci. Comput. Program.
Néstor Cataño, Ijaz Ahmed, Radu I. Siminiceanu, Jonathan Aldrich
2012 J jnl
Electron. Commun. Eur. Assoc. Softw. Sci. Technol.
Radu I. Siminiceanu, Ijaz Ahmed, Néstor Cataño
2012
Ijaz Ahmed
2011 C conf
FMICS
Néstor Cataño, Ijaz Ahmed
2008 conf
Software Engineering Research and Practice
Samina Jadoon, Kashif Hesham Khan, Ijaz Ahmed
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