Insaf Ullah

52 papers B 1Journal 49Unranked 2
YearRankTypeTitle / Venue / Authors
2026 J jnl
Internet Things
Insaf Ullah, Syed Tariq Shah, Wali Ullah Khan, Mahmoud A. Shawky, Ahmad Almogren, Haralambos Mouratidis
2026 J jnl
Internet Things
Junaid, Hassan Malik, Fahad Algarni, Insaf Ullah
2026 J jnl
Comput. Math. Methods
Mahwish Bano, Umair Habib, Jawaid Iqbal, Hassan Malik, Insaf Ullah
2025 J jnl
J. Cloud Comput.
Tarek Abid, Ahmed Ahmim, Faiz Maazouzi, Djalel Chefrour, Insaf Ullah, Marwa Ahmim, Reham Almukhlifi
2025 J jnl
IEEE Trans. Intell. Transp. Syst.
Muhammad Asghar Khan, Insaf Ullah, Neeraj Kumar, Adnan Akhunzada, Mohammad Hossein Anisi, Abdulmajeed Alqhatani, Fatemeh Afghah, Gordana Barb, Abi Waqas
2025 J jnl
CoRR
Abdul Haque, Umm e Hani, Ahmad Din, Muhammad Babar, Ali Abbas, Insaf Ullah
2025 J jnl
Comput. Mater. Continua
Marwa Ahmim, Nour Ouafi, Insaf Ullah, Ahmed Ahmim, Djalel Chefrour, Reham Almukhlifi
2025 J jnl
Clust. Comput.
Rafiq Ullah, Amjad Mehmood, Muhammad Altaf Khan, Insaf Ullah
2025 J jnl
Internet Things
Abdelghani Dahou, Syed Tariq Shah, Insaf Ullah, Tahira Mahboob, Ahmed Gamal Abdellatif, Mohamed Abd Elaziz, Ahmad Almogren, Mahmoud A. Shawky
2025 B conf
PIMRC
Mahmoud A. Shawky, Syed Tariq Shah, Ahmed Gamal, Wali Ullah Khan, Insaf Ullah, Rana Muhammad Sohaib, Gagangeet Singh Aujla
2025 J jnl
IEEE Trans. Netw. Serv. Manag.
Muhammad Asghar Khan, Neeraj Kumar, Saeed Hamood Alsamhi, Gordana Barb, Justyna Zywiolek, Insaf Ullah, Fazal Noor, Jawad Ali Shah, Abdullah Mohammed Almuhaideb
2025 J jnl
Internet Things
Sabrina Sakraoui, Makhlouf Derdour, Ahmed Ahmim, Reham Almukhlifi, Marwa Ahmim, Insaf Ullah
2024 J jnl
IEEE Access
Muhammad Asghar Khan, Insaf Ullah, Neeraj Kumar, Fatemeh Afghah, Gordana Barb, Fazal Noor, Saad Alqahtany
2024 conf
ICECET
Syed Waleed Riaz, Fazlullah Khan, Insaf Ullah, Bandar Alshawi, Ryan Alturki, Mohammad O. Wedyan
2024 J jnl
IEEE Open J. Commun. Soc.
Muhammad Asghar Khan, Shumaila Javaid, Syed Agha Hassnain Mohsan, Muhammad Tanveer, Insaf Ullah
2024 conf
ICDF2C (1)
Hassan Jalil Hadi, Yue Cao, Faisal Bashir Hussain, Naveed Ahmad, Mohammed Ali Alshara, Insaf Ullah, Yasir Javed, Yinglong He, Abdul Majid Jamil
2023 J jnl
IEEE Trans. Veh. Technol.
Insaf Ullah, Muhammad Asghar Khan, Neeraj Kumar, Ako Muhammad Abdullah, Abeer Abdul-Aziz Alsanad, Fazal Noor
2023 J jnl
Sensors
Muhammad Asghar Khan, Hosam Alhakami, Wajdi Alhakami, Alexey V. Shvetsov, Insaf Ullah
2023 J jnl
Clust. Comput.
Asad Ullah Khan, Nadeem Javaid, Muhammad Asghar Khan, Insaf Ullah
2023 J jnl
J. Sens. Actuator Networks
Tahir Ali Shah, Insaf Ullah, Muhammad Asghar Khan, Pascal Lorenz, Nisreen Innab
2023 J jnl
Sensors
Muhammad Asghar Khan, Insaf Ullah, Ako Muhammad Abdullah, Syed Agha Hassnain Mohsan, Fazal Noor
2023 J jnl
Future Internet
Asad Iqbal, Muhammad Zubair, Muhammad Asghar Khan, Insaf Ullah, Ghani Ur Rehman, Alexey V. Shvetsov, Fazal Noor
2023 J jnl
Future Internet
Zainab Jamroz, Insaf Ullah, Bilal Hassan, Noor Ul Amin, Muhammad Asghar Khan, Pascal Lorenz, Nisreen Innab
2023 J jnl
Sensors
Insaf Ullah, Muhammad Asghar Khan, Ako Muhammad Abdullah, Fazal Noor, Nisreen Innab, Chien-Ming Chen
2023 J jnl
Internet Things
Usman Ali, Mohd Yamani Idna Bin Idris, Jaroslav Frnda, Mohamad Nizam Bin Ayub, Muhammad Asghar Khan, Nauman Khan, T. Rehannara Beegum, Ahmed Abdulhadi Jasim, Insaf Ullah, Mohammad Babar
2023 J jnl
IEEE Trans. Netw. Serv. Manag.
Muhammad Asghar Khan, Neeraj Kumar, Syed Agha Hassnain Mohsan, Wali Ullah Khan, Moustafa M. Nasralla, Mohammed H. Alsharif, Justyna Zywiolek, Insaf Ullah
2022 J jnl
IEEE Trans. Ind. Informatics
Muhammad Asghar Khan, Insaf Ullah, Ali Alkhalifah, Sajjad ur Rehman, Jawad Ali Shah, Muhammad Irfan Uddin, Mohammed H. Alsharif, Fahad Algarni
2022 J jnl
IEEE Internet Things J.
Insaf Ullah, Muhammad Asghar Khan, Fazlullah Khan, Mian Ahmad Jan, Ram Srinivasan, Spyridon Mastorakis, Saddam Hussain, Hizbullah Khattak
2022 J jnl
IEEE Access
Insaf Ullah, Abdullah Alomari, Ako Muhammad Abdullah, Neeraj Kumar, Amjad Alsirhani, Fazal Noor, Saddam Hussain, Muhammad Asghar Khan
2022 J jnl
Complex.
Tahir Ali Shah, Fahad Algarni, Insaf Ullah, Ako Muhammad Abdullah, Fazal Noor, Muhammad Asghar Khan
2022 J jnl
J. Sensors
Amna Ikram, Waqar Aslam, Roza Hikmat Hama Aziz, Fazal Noor, Ghulam Ali Mallah, Sunnia Ikram, Muhammad Saeed Ahmad, Ako Muhammad Abdullah, Insaf Ullah
2022 J jnl
J. Circuits Syst. Comput.
Fazal Subhan, Suheel Abdullah Malik, Muhammad Asghar Khan, Muhammad Adnan Aziz, Muhammad Irfan Uddin, Insaf Ullah
2022 J jnl
CoRR
Muhammad Asghar Khan, Neeraj Kumar, Syed Agha Hassnain Mohsan, Wali Ullah Khan, Moustafa M. Nasralla, Mohammed H. Alsharif, Justyna Zywiolek, Insaf Ullah
2022 J jnl
Comput. Syst. Sci. Eng.
Faisal Bahadur, Arif Iqbal Umar, Insaf Ullah, Fahad Algarni, Muhammad Asghar Khan
2021 J jnl
Mob. Inf. Syst.
Muhammad Asghar Khan, Tanweer Ahmad Cheema, Insaf Ullah, Fazal Noor, Sajjad ur Rehman, Ateeq Ur Rehman, Muhammad Adnan Aziz
2021 J jnl
J. Inf. Secur. Appl.
Saddam Hussain, Insaf Ullah, Hizbullah Khattak, Muhammad Asghar Khan, Chien-Ming Chen, Saru Kumari
2021 J jnl
IEEE Access
Insaf Ullah, Ali Alkhalifah, Sajjad ur Rehman, Neeraj Kumar, Muhammad Asghar Khan
2021 J jnl
Comput. Syst. Sci. Eng.
Muhammad Asghar Khan, Fazal Noor, Insaf Ullah, Sajjad ur Rehman, Shibli Nisar, Mohaira Ahmad
2021 J jnl
J. Medical Syst.
Insaf Ullah, Noor Ul Amin, Muhammad Asghar Khan, Hizbullah Khattak, Saru Kumari
2021 J jnl
IEEE Trans. Veh. Technol.
Muhammad Asghar Khan, Insaf Ullah, Neeraj Kumar, Omar Sami Oubbati, Ijaz Mansoor Qureshi, Fazal Noor, Fahim Ullah Khanzada
2021 J jnl
Mob. Inf. Syst.
Insaf Ullah, Ali Alkhalifah, Muhammad Asghar Khan, Samih Mohemmed Mostafa
2021 J jnl
Microprocess. Microsystems
Insaf Ullah, Sherali Zeadally, Noor Ul Amin, Muhammad Asghar Khan, Hizbullah Khattak
2021 J jnl
IEEE Access
Usman Ali, Mohd Yamani Idna Bin Idris, Mohamad Nizam Bin Ayub, Insaf Ullah, Ihsan Ali, Tarak Nandy, Muktar Yahuza, Nauman Khan
2021 J jnl
IEEE Access
Muhammad Asghar Khan, Habib Shah, Sajjad ur Rehman, Neeraj Kumar, Rozaida Ghazali, Danish Shehzad, Insaf Ullah
2020 J jnl
IEEE Access
Syed Sajid Ullah, Insaf Ullah, Hizbullah Khattak, Muhammad Asghar Khan, Muhammad Adnan, Saddam Hussain, Noor Ul Amin, Muazzam Ali Khan Khattak
2020 J jnl
Wirel. Commun. Mob. Comput.
Manazara Rehman, Hizbullah Khattak, Ahmed Saeed Alzahrani, Insaf Ullah, Muhammad Adnan, Syed Sajid Ullah, Noor Ul Amin, Saddam Hussain, Shah Jahan Khattak
2020 J jnl
IEEE Access
Saddam Hussain, Insaf Ullah, Hizbullah Khattak, Muhammad Adnan, Saru Kumari, Syed Sajid Ullah, Muhammad Asghar Khan, Shah Jahan Khattak
2020 J jnl
IEEE Access
Insaf Ullah, Noor Ul Amin, Ahmad Almogren, Muhammad Asghar Khan, Muhammad Irfan Uddin, Qiaozhi Hua
2020 J jnl
IEEE Access
Muhammad Asghar Khan, Insaf Ullah, Shibli Nisar, Fazal Noor, Ijaz Mansoor Qureshi, Fahim Ullah Khanzada, Noor Ul Amin
2020 J jnl
Mob. Inf. Syst.
Zahid Ullah, Asim Zeb, Insaf Ullah, Khalid Mahmood Awan, Yousaf Saeed, Muhammad Irfan Uddin, Mahmoud Ahmad Al-Khasawneh, Marwan Mahmoud, Mahdi Zareei
2020 J jnl
Mob. Inf. Syst.
Muhammad Asghar Khan, Insaf Ullah, Shibli Nisar, Fazal Noor, Ijaz Mansoor Qureshi, Fahim Ullah Khanzada, Hizbullah Khattak, Muhammad Adnan Aziz
2019 J jnl
Symmetry
Insaf Ullah, Noor Ul Amin, Mahdi Zareei, Asim Zeb, Hizbullah Khattak, Ajab Khan, Shidrokh Goudarzi
redb/extractors/decompiler/bninja/analysis/disassembly.py
← Index redb/extractors/decompiler/bninja/analysis/disassembly.py python
import re
import time

import binaryninja
from binaryninja.enums import (
    InstructionTextTokenType,
)

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


class DisassemblyAnalysis:
    INVALID_STACK_SIZE = -1

    def __init__(self, arch, function, bv, logger):
        self.arch = arch
        self.function = function
        self.bv = bv
        self.logger = logger
        if self.function is not None and hasattr(self.function, "instructions"):
            self.instructions = self.function.instructions
        else:
            self.instructions = []
        self.errors = []
        return

    def log_error(
        self, message, function_name, address, exception=None, error_location="unknown"
    ):
        """Log an error during processing."""
        error_msg = f"Error in function {function_name} at {address}: {message}"
        if exception:
            error_msg += f" - {str(exception)}"
        self.logger.error(error_msg)

        # Add to errors list
        error = {
            "function_name": function_name,
            "function_address": str(address),
            "error_location": error_location,
            "error_message": message,
            "error_details": str(exception) if exception else "",
            "error_type": type(exception).__name__ if exception else "Unknown",
            "timestamp": int(time.time() * 1000),
        }
        self.errors.append(error)

    def get_json(self):
        try:
            # Build disassembly string and normalized versions
            disassembly_builder = [[], []]  # Address and instruction text

            # Create a dictionary mapping addresses to instruction tokens
            instr_tokens_by_addr = {}
            for instr_tokens, addr in self.instructions:
                instr_tokens_by_addr[addr] = instr_tokens

            addresses = sorted(instr_tokens_by_addr.keys())
            for address in addresses:
                # Original disassembly with addresses
                # instr_tokens, address = instruction
                instr_tokens = instr_tokens_by_addr[address]
                disassembly_builder[0].append(address)
                disassembly_builder[1].append("".join(map(str, instr_tokens)))

            # Join with newlines
            disassembly_str = "\n".join(disassembly_builder[1])
            disassembly_with_addresses = "\n".join(
                f"{hex(address)}: {instr_text}"
                for address, instr_text in zip(
                    disassembly_builder[0], disassembly_builder[1], strict=False
                )
            )

            disassembly_json = {
                "disassembled_function_hash": calculate_sha256(disassembly_str),
                "disassembled_function": disassembly_with_addresses,
                "disassembled_function_no_addresses": disassembly_str,
                "disassembled_function_name": self.function.name,
                "disassembled_function_address": self.function.start,
                "instructions_count": len(instr_tokens_by_addr.keys()),
                "function_type": FunctionTypeAnalysis(self.function)
                .get_function_type()
                .name,
            }

            # Add additional metrics
            type_frequencies = self.collect_instruction_types()
            disassembly_json["instructions_types"] = list(type_frequencies.keys())
            disassembly_json["control_flow_count"] = (
                self.count_control_flow_instructions()
            )
            disassembly_json["memory_access_pattern"] = self.collect_memory_patterns()
            disassembly_json["register_usage"] = self.collect_register_usage()
            disassembly_json["data_references_count"] = self.count_data_references()
            disassembly_json["max_block_size"] = self.compute_max_block_size()
            disassembly_json["num_calls"] = self.compute_num_calls()
            disassembly_json["stack_size"] = self.estimate_stack_size()

            return disassembly_json, self.errors

        except Exception as e:
            self.log_error(
                "Failed to collect instruction types",
                self.function.name,
                self.function.start,
                e,
                "collect_instruction_types",
            )
            raise ValueError(e) from e

    def collect_instruction_types(self):
        """Collect instruction type frequencies from a function."""
        type_frequencies = {}

        try:
            # Iterate through all instructions in the function
            for instruction in self.instructions:
                instr_tokens = instruction[0]  # Get the instruction tokens

                # Extract the mnemonic from the instruction tokens
                mnemonic = None
                for token in instr_tokens:
                    if token.type == InstructionTextTokenType.InstructionToken:
                        mnemonic = token.text
                        break

                if not mnemonic:
                    continue

                # Use normalize_opcode to get standardized opcode
                normalized = self.normalize_opcode(mnemonic)

                # Get category from opcode_categories or use the instruction type directly
                category = self.arch.opcode_categories.get(normalized)
                if category:
                    self._increment_frequency(type_frequencies, category)

        except Exception as e:
            self.log_error(
                "Failed to collect instruction types",
                self.function.name,
                self.function.start,
                e,
                "collect_instruction_types",
            )

        return type_frequencies

    def normalize_opcode(self, opcode):
        return opcode.upper()

    def collect_memory_patterns(self):
        """Collect memory access patterns from a function."""
        patterns = []
        try:
            for instruction in self.instructions:
                instr_tokens = instruction[0]

                # We need to capture memory operands between BeginMemoryOperandToken and EndMemoryOperandToken
                in_memory_operand = False
                memory_operand_text = ""

                for token in instr_tokens:
                    if token.type == InstructionTextTokenType.BeginMemoryOperandToken:
                        in_memory_operand = True
                        memory_operand_text = ""
                    elif token.type == InstructionTextTokenType.EndMemoryOperandToken:
                        in_memory_operand = False

                        # Process the captured memory operand text
                        if memory_operand_text:
                            # Categorize memory access pattern
                            if (
                                "+" in memory_operand_text
                                and "*" in memory_operand_text
                            ):
                                if "MEM_SCALED_INDEX" not in patterns:
                                    patterns.append("MEM_SCALED_INDEX")
                            elif (
                                "+" in memory_operand_text or "-" in memory_operand_text
                            ):
                                if "MEM_BASE_OFFSET" not in patterns:
                                    patterns.append("MEM_BASE_OFFSET")
                            else:
                                if "MEM_DIRECT" not in patterns:
                                    patterns.append("MEM_DIRECT")

                            # Check for stack accesses
                            if any(
                                reg in memory_operand_text
                                for reg in ["SP", "BP", "ESP", "EBP", "RSP", "RBP"]
                            ):
                                if "MEM_STACK" not in patterns:
                                    patterns.append("MEM_STACK")
                            # Check for string operations
                            elif (
                                any(
                                    reg in memory_operand_text
                                    for reg in ["SI", "DI", "ESI", "EDI", "RSI", "RDI"]
                                )
                                and "MEM_STRING" not in patterns
                            ):
                                patterns.append("MEM_STRING")
                    elif in_memory_operand:
                        # Accumulate token text while inside a memory operand
                        memory_operand_text += token.text
        except Exception as e:
            self.log_error(
                "Failed to collect memory patterns",
                self.function.name,
                self.function.start,
                e,
                "collect_memory_patterns",
            )
        return patterns

    def collect_register_usage(self):
        """Collect register usage from a function."""
        registers = []
        try:
            # Define register groups we're interested in tracking
            register_groups = {
                "GPR": [
                    "RAX",
                    "RBX",
                    "RCX",
                    "RDX",
                    "R9",
                    "R10",
                    "R11",
                    "R12",
                    "R13",
                    "R14",
                    "R15",
                    "EAX",
                    "EBX",
                    "ECX",
                    "EDX",
                    "R9D",
                    "R10D",
                    "R11D",
                    "R12D",
                    "R13D",
                    "R14D",
                    "AX",
                    "BX",
                    "CX",
                    "DX",
                ],
                "GPR_INDEX": ["RSI", "RDI", "ESI", "EDI", "SI", "DI"],
                "GPR_STACK": ["RSP", "RBP", "ESP", "EBP", "SP", "BP"],
                "SIMD": ["XMM", "YMM", "ZMM"],
                "FPU": ["ST", "ST0", "ST1", "ST2", "ST3", "ST4", "ST5", "ST6", "ST7"],
                "FLAGS": ["FLAGS", "EFLAGS", "RFLAGS"],
                "CONTROL_REGISTER": ["CR0", "CR2", "CR3", "CR4", "CR8"],
                "DEBUG_REGISTER": ["DR0", "DR1", "DR2", "DR3", "DR6", "DR7"],
            }

            # Extract registers from instructions
            for instruction in self.instructions:
                instr_tokens = instruction[0]
                for token in instr_tokens:
                    if token.type == InstructionTextTokenType.RegisterToken:
                        reg = token.text.upper()
                        # Check which group this register belongs to
                        for group, regs in register_groups.items():
                            # if any(r in reg for r in regs) or any(reg.startswith(r) for r in regs):
                            if any(reg == r or reg.startswith(r) for r in regs):
                                if group not in registers:
                                    registers.append(group)
                                break
        except Exception as e:
            self.log_error(
                "Failed to collect register usage",
                self.function.name,
                self.function.start,
                e,
                "collect_register_usage",
            )
        return registers

    def count_data_references(self):
        """Count the number of data references in a function."""
        count = 0
        try:

            if self.function.mlil is None:
                return 0

            for block in self.function.mlil:
                for instr in block:
                    instr_str = str(instr)
                    logged = False
                    src = None

                    # Check for constant dereferencing or symbolic refs
                    if hasattr(instr, "src"):
                        src = instr.src
                        if isinstance(
                            src,
                            (
                                binaryninja.mediumlevelil.MediumLevelILConstPtr,
                                binaryninja.mediumlevelil.MediumLevelILConst,
                            ),
                        ):
                            count += 1
                            logged = True

                    # Check full string for hardcoded addresses or symbol-like tokens
                    if re.search(r"\b0x[0-9A-Fa-f]{3,}\b", instr_str) and not logged:
                        count += 1
                        logged = True

                    if "_" in instr_str and not logged:
                        count += 1
                        logged = True

                    # Only check for MediumLevelILConstPtr if src exists
                    if src is not None and isinstance(
                        src, binaryninja.mediumlevelil.MediumLevelILConstPtr
                    ):
                        addr = src.constant
                        # Check if address is in data sections
                        segment = self.bv.get_segment_at(addr)
                        if segment and segment.writable:
                            # print(f"[{function.name}] Matched data section reference in: {instr_str}")
                            count += 1
                            logged = True
        except Exception as e:
            self.logger.warning(
                f"Failed to use MLIL for counting data references in {self.function.name} at {self.function.start}: {e}"
            )
        return count

    def compute_max_block_size(self):
        """Compute the maximum basic block size in a function."""
        max_size = 0
        if self.function is None:
            return 0

        for block in self.function.basic_blocks:
            try:
                # Count instructions in this block using the direct length approach
                # This avoids UTF-8 decoding issues entirely
                block_size = block.instruction_count
                max_size = max(max_size, block_size)
            except Exception as e:
                self.log_error(
                    f"[HandledError] computing max block size: {e}",
                    self.function.name,
                    self.function.start,
                    e,
                    "compute_max_block_size",
                )
        return max_size

    def count_control_flow_instructions(self):
        """Count the number of control flow instructions in a function."""
        count = 0
        try:
            for instruction in self.instructions:
                instr_tokens = instruction[0]
                if self.arch.is_control_flow_instruction(instr_tokens):
                    count += 1
        except Exception as e:
            self.log_error(
                "Failed to count control flow instructions",
                self.function.name,
                self.function.start,
                e,
                "count_control_flow_instructions",
            )
        return count

    def compute_num_calls(self) -> int:
        """Compute the number of call instructions in a function."""
        num_calls = 0
        try:
            for instruction in self.instructions:
                instr_tokens = instruction[0]
                # Extract the mnemonic
                for token in instr_tokens:
                    if token.type == InstructionTextTokenType.InstructionToken:
                        if token.text.upper() == "CALL":
                            num_calls += 1
                        break
        except Exception as e:
            self.log_error(
                "Failed to compute number of calls",
                self.function.name,
                self.function.start,
                e,
                "compute_num_calls",
            )
        return num_calls

    def _increment_frequency(self, frequencies, type_name):
        """Increment the frequency count for an instruction type."""
        if type_name in frequencies:
            frequencies[type_name] += 1
        else:
            frequencies[type_name] = 1

    def estimate_stack_size(self):
        """Estimate the stack size used by a function."""
        try:
            # Binary Ninja provides a stack adjustment value for functions
            # Need to convert OffsetWithConfidence to a plain integer
            stack_adjust = self.function.stack_adjustment
            if hasattr(stack_adjust, "value"):  # Handle OffsetWithConfidence objects
                return stack_adjust.value
            return stack_adjust
        except Exception as e:
            self.log_error(
                "Failed to estimate stack size",
                self.function.name,
                self.function.start,
                e,
                "estimate_stack_size",
            )
            return self.INVALID_STACK_SIZE