Wail Mardini

57 papers B 1C 12Misc 1Journal 29Unranked 14
YearRankTypeTitle / Venue / Authors
2023 conf
ICNCC
Tawbah Ennab, Yaser M. Khamayseh, Wail Mardini, Yu Shen, Burak Kantarci
2023 J jnl
J. Ambient Intell. Humaniz. Comput.
Omar AlZoubi, Buthina AlMakhadmeh, Muneer O. Bani Yassein, Wail Mardini
2022 J jnl
Int. J. Commun. Networks Inf. Secur.
Mohammad Malkawi, Wail Mardini, Toqa' Abu Zaitoun
2022 conf
IOTSMS
Firas AlBalas, Ehssan Alrabee, Wail Mardini, Amr Sawafta
2022 J jnl
IEEE Access
Marah R. Bataineh, Wail Mardini, Yaser M. Khamayseh, Muneer O. Bani Yassein
2021 J jnl
IEEE Netw. Lett.
Yuwei Wang, Burak Kantarci, Wail Mardini
2021 J jnl
Int. J. Commun. Networks Inf. Secur.
Rana Al-Rawashdeh, Mohammad Al-Fawa'reh, Wail Mardini
2021 J jnl
Int. J. Commun. Networks Inf. Secur.
Rana Al-Rawashdeh, Mohammad Al-Fawa'reh, Wail Mardini
2021 J jnl
Mob. Networks Appl.
Wail Mardini, Shadi A. Aljawarneh, Amnah Al-Abdi
2020 J jnl
Int. J. Commun. Syst.
Issam W. Damaj, Wail Mardini, Hussein T. Mouftah
2020 J jnl
Expert Syst. J. Knowl. Eng.
Yaser M. Khamayseh, Wail Mardini, J. William Atwood, Monther Aldwairi
2020 J jnl
IEEE Access
Wail Mardini, M. Masadeh Bani Yassein, Rana Al-Rawashdeh, Shadi A. Aljawarneh, Yaser M. Khamayseh, Omar Meqdadi
2020 J jnl
J. Wirel. Mob. Networks Ubiquitous Comput. Dependable Appl.
Yaser M. Khamayseh, Wail Mardini, Monther Aldwairi, Hussein T. Mouftah
2019 C conf
DATA
Firas AlBalas, Majd Al-Soud, Wail Mardini
2019 conf
CCWC
Firas AlBalas, Wail Mardini, Majd Al-Soud, Qussai Yaseen
2019 C conf
DATA
Abdullah Melhem, Omar AlZoubi, Wail Mardini, Muneer O. Bani Yassein
2019 C conf
AICCSA
Muneer O. Bani Yassein, Farah Shatnawi, Saif Rawashdeh, Wail Mardini
2019 C conf
DATA
Muneer O. Bani Yassein, Ismail Hmeidi, Marwa Al-Harbi, Lina Mrayan, Wail Mardini, Yaser M. Khamayseh
2019 C conf
DATA
Hadeel Alazzam, Abdulsalam Alsmady, Wail Mardini, Amira Enizat
2019 C conf
IoTBDS
Muneer O. Bani Yassein, Ismail Hmeidi, Haneen Shehadeh, Waed Bani Yaseen, Esra'a Masa'deh, Wail Mardini, Yaser M. Khamayseh, Qanita Bani Baker
2019 conf
ICSIE
Muneer O. Bani Yassein, Ameena Flefil, Dragana Krstic, Yaser M. Khamayseh, Wail Mardini, Mohammed Q. Shatnawi
2019 conf
EUSPN/ICTH
Muneer O. Bani Yassein, Ismail Hmeidi, Farah Shatnawi, Wail Mardini, Yaser M. Khamayseh
2019 C conf
DATA
Amnah Al-Abdi, Wail Mardini, Shadi A. Aljawarneh, Tareq Abed Mohammed
2018 conf
ICFNDS
Haneen Shehadeh, Wail Mardini, Muneer O. Bani Yassein, Doaa Habeeb Allah, Waed Bani Yaseen
2018 C conf
DATA
Wail Mardini, Muneer O. Bani Yassein, Mohammad AlRashdan, Abdalraheem Alsmadi, Ahmad Bani Amer
2018 conf
ICFNDS
Amr Abu Abdo, Raffi Al-Qurran, Wail Mardini
2018 J jnl
J. Comput.
Yaser M. Khamayseh, Wail Mardini, Nadhir Ben Halima
2018 J jnl
Comput. Electr. Eng.
Wail Mardini, Yaser M. Khamayseh, Muneer O. Bani Yassein, Montaha Hani Khatatbeh
2017 conf
FMEC
Firas AlBalas, Wail Mardini, Majd Al-Soud
2017 J jnl
Comput. Syst. Sci. Eng.
Wail Mardini, Yaser M. Khamayseh, Marwa Salayma, Muneer O. Bani Yassein, Hussein T. Mouftah
2017 J jnl
Int. J. Commun. Networks Inf. Secur.
Wail Mardini, Maad Ebrahim, Mohammed Al-Rudaini
2017 conf
ICIME
Wail Mardini, Yaser M. Khamayseh, Ashraf Smadi
2017 J jnl
Int. J. Commun. Networks Inf. Secur.
Firas AlBalas, Wail Mardini, Dua'a Bani-salameh
2016 J jnl
Peer-to-Peer Netw. Appl.
Wail Mardini, Yaser M. Khamayseh, Abedl Rahman Almodawar, Ehab S. Elmallah
2015 conf
CIT/IUCC/DASC/PICom
Nadhir Ben Halima, Yaser M. Khamayseh, Wail Mardini, Abedl Rahman Almodawar
2015 J jnl
Int. J. Inf. Commun. Technol. Educ.
Yaser M. Khamayseh, Wail Mardini, Shadi A. Aljawarneh, Muneer O. Bani Yassein
2015 J jnl
Intell. Autom. Soft Comput.
Yaser M. Khamayseh, Wail Mardini, Hadeel Tbashate
2015 J jnl
Ad Hoc Sens. Wirel. Networks
Yaser M. Khamayseh, Wail Mardini, Rana Al-Hijjawi, Reem Jaradat, Hussein T. Mouftah
2013 conf
MobiWIS
Muneer Bani Yasin, Maryan Yatim, Marwa Salaymeh, Yaser M. Khamayseh, Wail Mardini
2012 J jnl
Netw. Protoc. Algorithms
Wail Mardini, Yaser M. Khamayseh
2012 J jnl
Netw. Protoc. Algorithms
Muneer O. Bani Yassein, Marwa Salayma, Wail Mardini, Yaser M. Khamayseh
2012 J jnl
Netw. Protoc. Algorithms
Ahmad Abed Elellah Momani, Muneer O. Bani Yassein, Omar Darwish, Saher S. Manaseer, Wail Mardini
2012 J jnl
Int. J. Parallel Emergent Distributed Syst.
Ismail Ababneh, Saad Bani-Mohammad, Wail Mardini, Hilal Alawneh, Mohammad Hamed
2011 B conf
IWCMC
Basel Alawieh, Wail Mardini, Hussein T. Mouftah
2011 J jnl
Int. J. Commun. Networks Inf. Secur.
Yaser M. Khamayseh, Abdulraheem Bader, Wail Mardini, Muneer O. Bani Yassein
2011 J jnl
Int. J. Mob. Comput. Multim. Commun.
Yaser M. Khamayseh, Muneer O. Bani Yassein, Iman I. Badran, Wail Mardini
2011 J jnl
Netw. Protoc. Algorithms
Wail Mardini, Mai Abu Alfool
2011 conf
ANT/MobiWIS
Wail Mardini, Yaser M. Khamayseh, Marwa Salayma
2010 C conf
CIT
Ismail Ababneh, Wail Mardini, Hilal Alawneh, Mohammad Hamed, Saad Bani-Mohammad
2010 C conf
CIT
Muneer O. Bani Yassein, Osama Al Oqaily, Geyong Min, Wail Mardini, Yaser M. Khamayseh, Saher S. Manaseer
2009 J jnl
J. Digit. Content Technol. its Appl.
Mohammad Ghaleb Ali, Wail Mardini, Akbar Ghaffar Pour Rahbar, Yaser M. Khamayseh
2009 J jnl
J. Digit. Content Technol. its Appl.
Muneer O. Bani Yassein, A. Al-zou'bi, Yaser M. Khamayseh, Wail Mardini
2009 conf
IADIS AC (2)
Yaser M. Khamayseh, Wail Mardini, Muneer O. Bani Yassein
2006 Misc conf
CISS
Wail Mardini, Oliver W. W. Yang
2006 C conf
BROADNETS
Wail Mardini, Oliver W. W. Yang
2006 conf
CCECE
Wail Mardini, Oliver W. W. Yang
2004 C conf
ISCC
Shahram Shah-Heydari, Wail Mardini, Oliver W. W. Yang
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