Mahmoud Hamouda

35 papers C 11Journal 15Unranked 9
YearRankTypeTitle / Venue / Authors
2025 conf
SMACD
Mohamed Belguith, Sonia Eloued, Moncef Kadi, Jaleleddine Ben Hadj Slama, Mahmoud Hamouda
2025 J jnl
IEEE Access
Mahmoud Hamouda, Hanaa Elsherbiny, Alaa A. Zaky, Ismoil Odinaev, Vladimír Bures, Amir Abdel Menaem
2025 J jnl
IEEE Access
Mahmoud I. Elkasas, Ameer Lateef Saleh, Abdelhady Ghanem, Mohamed F. Kotb, Mahmoud Hamouda
2024 J jnl
IEEE Access
Fathia Letaief, Mahmoud Hamouda, Mohamed Ali Belaïd, Kamal Al-Haddad
2024 J jnl
IEEE Trans. Instrum. Meas.
Mohamed Mellouli, Mahmoud Hamouda, Hafiz Ahmed, Jaleleddine Ben Hadj Slama, Kamal Al-Haddad
2024 J jnl
IEEE Access
Mahmoud Hamouda, Fahad Al-Amyal, Hanaa Elsherbiny, Ismoil Odinaev, Amir Abdel Menaem, Khalil Alluhaybi, Alaa A. Zaky
2022 J jnl
IEEE Trans. Instrum. Meas.
Ibtissem Abari, Mahmoud Hamouda, Mohammad Sleiman, Jaleleddine Ben Hadj Slama, Hadi Youssef Kanaan, Kamal Al-Haddad
2022 C conf
IECON
Wajdi Budahab, Mahmoud Hamouda, Kamal Al-Haddad
2021 conf
ISIE
Kawther Ezzeddine, Mahmoud Hamouda, Hadi Youssef Kanaan, Kamal Al-Haddad
2021 conf
SSD
Fathia Letaief, Asma Ben Rhouma, Mahmoud Hamouda
2021 J jnl
Period. Polytech. Electr. Eng. Comput. Sci.
Laith Al Quraan, László Számel, Mahmoud Hamouda
2020 conf
ICIT
Amira Ammar, Hadi Youssef Kanaan, Nazih Moubayed, Mahmoud Hamouda, Kamal Al-Haddad
2020 C conf
IECON
Amira Ammar, Hadi Youssef Kanaan, Mahmoud Hamouda, Kamal Al-Haddad
2020 J jnl
IEEE Access
Amira Ammar, Hadi Youssef Kanaan, Nazih Moubayed, Mahmoud Hamouda, Kamal Al-Haddad
2020 C conf
IECON
Kawther Ezzeddine, Mahmoud Hamouda, Hadi Youssef Kanaan, Kamal Al-Haddad
2019 J jnl
Period. Polytech. Electr. Eng. Comput. Sci.
Mahmoud Hamouda, László Számel
2019 C conf
IECON
Amira Ammar, Hadi Youssef Kanaan, Nazih Moubayed, Mahmoud Hamouda, Kamal Al-Haddad
2019 conf
ICIT
Amira Ammar, Hadi Youssef Kanaan, Nazih Moubayed, Mahmoud Hamouda, Hani Vahedi, Kamal Al-Haddad
2018 C conf
IECON
Amira Ammar, Hadi Youssef Kanaan, Nazih Moubayed, Mahmoud Hamouda, Kamal Al-Haddad
2018 J jnl
Turkish J. Electr. Eng. Comput. Sci.
Mahmoud Hamouda, László Számel
2018 conf
ICIT
Amira Ammar, Hadi Youssef Kanaan, Nazih Moubayed, Mahmoud Hamouda, Kamal Al-Haddad
2018 J jnl
IEEE Trans. Ind. Electron.
Ibtissem Abari, Ali Lahouar, Mahmoud Hamouda, Jaleleddine Ben Hadj Slama, Kamal Al-Haddad
2018 conf
SSD
Ibtissem Abari, Mahmoud Hamouda, Jaleleddine Ben Hadj Slama
2018 C conf
IECON
Ibtissem Abari, Mahmoud Hamouda, Jaleleddine Ben Hadj Slama, Kamal Al-Haddad
2018 conf
SSD
Zouhaira Ben Mahmoud, Mahmoud Hamouda, Adel Khedher
2017 C conf
IECON
Wajdi Budahab, Mahmoud Hamouda, Kamal Al-Haddad
2017 C conf
IECON
Amira Ammar, Hadi Youssef Kanaan, Nazih Moubayed, Mahmoud Hamouda, Kamal Al-Haddad
2017 C conf
IECON
Amira Ammar, Hadi Youssef Kanaan, Nazih Moubayed, Mahmoud Hamouda, Kamal Al-Haddad
2017 C conf
IECON
Kawther Ezzeddine, Mahmoud Hamouda, Kamal Al-Haddad
2017 J jnl
Turkish J. Electr. Eng. Comput. Sci.
Mohamed Salem, Mahmoud Hamouda, Jaleleddine Ben Hadj Slama
2017 conf
ICIT
Amira Ammar, Hadi Youssef Kanaan, Nazih Moubayed, Mahmoud Hamouda, Salem Rahmani, Youssef Ounejjar, Kamal Al-Haddad
2016 J jnl
IEEE Trans. Ind. Electron.
Mahmoud Hamouda, Handy Fortin-Blanchette, Kamal Al-Haddad
2015 J jnl
IEEE Trans. Ind. Electron.
Mahmoud Hamouda, Handy Fortin-Blanchette, Kamal Al-Haddad
2012 C conf
IECON
Mohamed Hamdi, Mahmoud Hamouda, Farhat Fnaiech, Kamal Al-Haddad
2011 J jnl
IEEE Trans. Ind. Electron.
Mahmoud Hamouda, Handy Fortin-Blanchette, Kamal Al-Haddad, Farhat Fnaiech
redb/extractors/decompiler/_archive/GhidraDecompilerScript-v2.java
← Index redb/extractors/decompiler/_archive/GhidraDecompilerScript-v2.java java
import ghidra.app.script.GhidraScript;
import ghidra.program.model.listing.*;
import ghidra.app.decompiler.*;
import ghidra.program.model.block.*;
import ghidra.program.model.symbol.*;
import ghidra.program.model.pcode.*;
import ghidra.program.model.address.*;
import org.json.JSONObject;
import org.json.JSONArray;
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;

public class GhidraDecompilerScript extends GhidraScript {
    private DecompInterface decompInterface;
    private BasicBlockModel basicBlockModel;

    @Override
    public void run() throws Exception {
        System.err.println("{\"debug\": \"Script starting\"}");

        // Get binary hash and filepath from arguments
        String[] args = getScriptArgs();
        if (args.length < 2) {
            System.err.println("{\"error\": \"Both SHA256 and filepath arguments are required\"}");
            return;
        }
        String sha256 = args[0];
        String filepath = args[1];

        // Add debug output after setup
        System.err.println("{\"debug\": \"Processing file: " + args[1] + "\"}");

        // Initialize analysis components
        setupDecompiler();
        basicBlockModel = new BasicBlockModel(currentProgram);

        // Create the main JSON object for output
        JSONObject output = new JSONObject();
        output.put("sha256", sha256);
        output.put("decompiled", new JSONArray());
        output.put("disassembled", new JSONArray());
        output.put("cfg", new JSONArray());

        // Process all functions
        FunctionIterator functions = currentProgram.getFunctionManager().getFunctions(true);
        for (Function function : functions) {
            processFunction(function, output);
        }

        System.err.println("{\"debug\": \"Preparing final output\"}");
        // Output the final JSON to stdout
        System.out.println(output.toString());
    }

    private void setupDecompiler() {
        decompInterface = new DecompInterface();
        DecompileOptions options = new DecompileOptions();
        decompInterface.setOptions(options);
        decompInterface.openProgram(currentProgram);
    }

    private void processFunction(Function function, JSONObject output) {
        try {
            Address entry = function.getEntryPoint();
            String functionName = function.getName();
            String functionAddress = entry.toString();

            // Process each analysis type independently
            boolean hasAnyResults = false;

            try {
                if (processDecompiledCode(function, output.getJSONArray("decompiled"),
                                        functionName, functionAddress)) {
                    hasAnyResults = true;
                }
            } catch (Exception e) {
                System.err.println(String.format(
                    "{\"error\": \"Decompilation failed for function %s: %s\"}",
                    functionName, e.getMessage().replace("\"", "'")));
            }

            try {
                if (processDisassembledCode(function, output.getJSONArray("disassembled"),
                                        functionName, functionAddress)) {
                    hasAnyResults = true;
                }
            } catch (Exception e) {
                System.err.println(String.format(
                    "{\"error\": \"Disassembly failed for function %s: %s\"}",
                    functionName, e.getMessage().replace("\"", "'")));
            }

            try {
                if (processCFG(function, output.getJSONArray("cfg"), functionAddress)) {
                    hasAnyResults = true;
                }
            } catch (Exception e) {
                System.err.println(String.format(
                    "{\"error\": \"CFG extraction failed for function %s: %s\"}",
                    functionName, e.getMessage().replace("\"", "'")));
            }

            if (!hasAnyResults) {
                System.err.println(String.format(
                    "{\"warning\": \"No results obtained for function %s\"}",
                    functionName));
            }

        } catch (Exception e) {
            System.err.println(String.format(
                "{\"error\": \"Failed to process function: %s\"}",
                e.getMessage().replace("\"", "'")));
        }
    }

    private boolean processDecompiledCode(Function function, JSONArray decompArray,
                                        String functionName, String functionAddress) {
        try {
            DecompileResults results = decompInterface.decompileFunction(function, 30, monitor);
            if (results == null || !results.decompileCompleted()) {
                System.err.println(String.format(
                    "{\"warning\": \"Decompilation incomplete for function %s\"}",
                    functionName));
                return false;
            }

            String decompiledCode = results.getDecompiledFunction().getC();
            if (decompiledCode == null || decompiledCode.trim().isEmpty()) {
                System.err.println(String.format(
                    "{\"warning\": \"Empty decompilation result for function %s\"}",
                    functionName));
                return false;
            }

            String contentHash = calculateHash(decompiledCode);

            JSONObject functionObj = new JSONObject();
            functionObj.put("decompiled_content_hash", contentHash);
            functionObj.put("decompiled_function_name", functionName);
            functionObj.put("decompiled_function_address", functionAddress);
            functionObj.put("decompiled_function", decompiledCode);

            decompArray.put(functionObj);
            return true;

        } catch (Exception e) {
            throw new RuntimeException("Decompilation error: " + e.getMessage(), e);
        }
    }

    private boolean processDisassembledCode(Function function, JSONArray disasmArray,
                                        String functionName, String functionAddress) {
        try {
            StringBuilder disassembly = new StringBuilder();
            StringBuilder normalized = new StringBuilder();
            int instructionCount = 0;
            boolean hasValidInstructions = false;

            Listing listing = currentProgram.getListing();
            AddressSetView functionBody = function.getBody();
            InstructionIterator instructions = listing.getInstructions(functionBody, true);

            while (instructions.hasNext()) {
                try {
                    Instruction instr = instructions.next();
                    if (instr != null) {
                        String disasmLine = instr.toString();
                        if (disasmLine != null && !disasmLine.trim().isEmpty()) {
                            disassembly.append(disasmLine).append("\n");
                            normalized.append(normalizeInstruction(disasmLine)).append("\n");
                            instructionCount++;
                            hasValidInstructions = true;
                        }
                    }
                } catch (Exception e) {
                    System.err.println(String.format(
                        "{\"warning\": \"Skipped invalid instruction in %s: %s\"}",
                        functionName, e.getMessage().replace("\"", "'")));
                }
            }

            if (!hasValidInstructions) {
                System.err.println(String.format(
                    "{\"warning\": \"No valid instructions found in function %s\"}",
                    functionName));
                return false;
            }

            String disassembledCode = disassembly.toString();
            String contentHash = calculateHash(disassembledCode);

            JSONObject functionObj = new JSONObject();
            functionObj.put("disassembled_content_hash", contentHash);
            functionObj.put("disassembled_function_name", functionName);
            functionObj.put("disassembled_function_address", functionAddress);
            functionObj.put("disassembled_function", disassembledCode);
            functionObj.put("normalized_disassembly", normalized.toString());
            functionObj.put("instruction_count", instructionCount);

            // Initialize similarity fields as null
            functionObj.put("minhash_signature", JSONObject.NULL);
            functionObj.put("opcode_frequency_vector", JSONObject.NULL);
            functionObj.put("api_calls_vector", JSONObject.NULL);
            functionObj.put("instruction_embedding", JSONObject.NULL);

            disasmArray.put(functionObj);
            return true;

        } catch (Exception e) {
            throw new RuntimeException("Disassembly error: " + e.getMessage(), e);
        }
    }

    private boolean processCFG(Function function, JSONArray cfgArray, String functionAddress) {
        try {
            CodeBlockIterator blocks = basicBlockModel.getCodeBlocksContaining(
                function.getBody(), monitor);

            boolean hasValidBlocks = false;

            while (blocks.hasNext()) {
                try {
                    CodeBlock block = blocks.next();
                    String blockInstructions = getBlockInstructions(block);

                    if (blockInstructions == null || blockInstructions.trim().isEmpty()) {
                        continue;
                    }

                    String blockId = calculateHash(blockInstructions);

                    JSONObject blockObj = new JSONObject();
                    blockObj.put("block_id", blockId);
                    blockObj.put("function_address", functionAddress);
                    blockObj.put("block_instructions", blockInstructions);

                    // Process successors with error handling
                    JSONArray successorAddresses = new JSONArray();
                    try {
                        CodeBlockReferenceIterator successors = block.getDestinations(monitor);
                        while (successors.hasNext()) {
                            try {
                                CodeBlockReference ref = successors.next();
                                if (ref != null && ref.getDestinationAddress() != null) {
                                    successorAddresses.put(ref.getDestinationAddress().toString());
                                }
                            } catch (Exception e) {
                                System.err.println(String.format(
                                    "{\"warning\": \"Skipped invalid successor in block %s: %s\"}",
                                    blockId, e.getMessage().replace("\"", "'")));
                            }
                        }
                    } catch (Exception e) {
                        System.err.println(String.format(
                            "{\"warning\": \"Error processing successors for block %s: %s\"}",
                            blockId, e.getMessage().replace("\"", "'")));
                    }

                    blockObj.put("successor_blocks", successorAddresses);
                    cfgArray.put(blockObj);
                    hasValidBlocks = true;

                } catch (Exception e) {
                    System.err.println(String.format(
                        "{\"warning\": \"Skipped invalid block in function %s: %s\"}",
                        functionAddress, e.getMessage().replace("\"", "'")));
                }
            }

            return hasValidBlocks;

        } catch (Exception e) {
            throw new RuntimeException("CFG extraction error: " + e.getMessage(), e);
        }
    }

    private String getBlockInstructions(CodeBlock block) {
        StringBuilder instructions = new StringBuilder();
        try {
            AddressIterator addresses = block.getAddresses(true);
            while (addresses.hasNext()) {
                try {
                    Address addr = addresses.next();
                    if (addr != null) {
                        Instruction instr = currentProgram.getListing().getInstructionAt(addr);
                        if (instr != null) {
                            instructions.append(instr.toString()).append("\n");
                        }
                    }
                } catch (Exception e) {
                    System.err.println(String.format(
                        "{\"warning\": \"Skipped invalid instruction at address %s: %s\"}",
                        addresses.next(), e.getMessage().replace("\"", "'")));
                }
            }
        } catch (Exception e) {
            System.err.println(String.format(
                "{\"warning\": \"Error getting block instructions: %s\"}",
                e.getMessage().replace("\"", "'")));
        }
        return instructions.toString();
    }

    private String normalizeInstruction(String instruction) {
        try {
            if (instruction == null || instruction.trim().isEmpty()) {
                return "";
            }
            return instruction.replaceAll("0x[0-9a-fA-F]+", "IMM")
                            .replaceAll("\\b\\d+\\b", "NUM")
                            .replaceAll("[\\[\\]\\+\\-\\*/%&|^]+", "_OP_");
        } catch (Exception e) {
            System.err.println(String.format(
                "{\"warning\": \"Error normalizing instruction: %s\"}",
                e.getMessage().replace("\"", "'")));
            return instruction;
        }
    }

    private String calculateHash(String content) {
        try {
            if (content == null || content.trim().isEmpty()) {
                return "";
            }
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(content.getBytes(StandardCharsets.UTF_8));
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                hexString.append(String.format("%02x", b));
            }
            return hexString.toString();
        } catch (Exception e) {
            System.err.println(String.format(
                "{\"error\": \"Error calculating hash: %s\"}",
                e.getMessage().replace("\"", "'")));
            return "";
        }
    }
}