James Devine

17 papers A* 3A 1B 2C 1Misc 2Journal 7Unranked 1
YearRankTypeTitle / Venue / Authors
2024 J jnl
Proc. ACM Program. Lang.
Thomas Ball, Peli de Halleux, James Devine, Steve Hodges, Michal Moskal
2024 Misc conf
IDC
Kobi Hartley, Elisa Rubegni, Lorraine Underwood, Joe Finney, Thomas Ball, Steve Hodges, Peli de Halleux, James Devine, Eric Anderson, Michal Moskal
2024 J jnl
GetMobile Mob. Comput. Commun.
James Devine, Steve Hodges, Thomas Ball, Michal Moskal, Peli de Halleux, Gabriele D'Amone, David Gakure, Joe Finney, Lorraine Underwood, Kobi Hartley, Matt Oppenheim, Paul Kos
2023 J jnl
Proc. ACM Interact. Mob. Wearable Ubiquitous Technol.
Mannu Lambrichts, Raf Ramakers, Steve Hodges, James Devine, Lorraine Underwood, Joe Finney
2023 B conf
TEI
Kobi Hartley, Joe Finney, Steve Hodges, Peli de Halleux, James Devine, Gabriele D'Amone
2022 A* conf
UIST
Venkatesh Potluri, John Thompson, James Devine, Bongshin Lee, Nora Morsi, Peli de Halleux, Steve Hodges, Jennifer Mankoff
2022 J jnl
Proc. ACM Interact. Mob. Wearable Ubiquitous Technol.
James Devine, Michal Moskal, Peli de Halleux, Thomas Ball, Steve Hodges, Gabriele D'Amone, David Gakure, Joe Finney, Lorraine Underwood, Kobi Hartley, Paul Kos, Matt Oppenheim
2022 A* conf
CHI
Johann Wentzel, Sasa Junuzovic, James Devine, John R. Porter, Martez E. Mott
2021 J jnl
Proc. ACM Interact. Mob. Wearable Ubiquitous Technol.
Mannu Lambrichts, Raf Ramakers, Steve Hodges, Sven Coppers, James Devine
2021 A* conf
CHI
Teddy Seyed, James Devine, Joe Finney, Michal Moskal, Peli de Halleux, Steve Hodges, Thomas Ball, Asta Roseway
2021 C conf
FDG
Michal Moskal, Thomas Ball, Abhijith Chatra, James Devine, Peli de Halleux, Steve Hodges, Shannon Kao, Richard Knoll, Galen Nickel, Jacqueline Russell, Joey Wunderlich, Daryl Zuniga
2020 J jnl
Commun. ACM
Jonny Austin, Howard Baker, Thomas Ball, James Devine, Joe Finney, Peli de Halleux, Steve Hodges, Michal Moskal, Gareth Stockdale
2019 A conf
Conference on Designing Interactive Systems
Bran Knowles, Sophie Beck, Joe Finney, James Devine, Joseph Lindley
2019 J jnl
J. Syst. Archit.
James Devine, Joe Finney, Peli de Halleux, Michal Moskal, Thomas Ball, Steve Hodges
2019 conf
CHI Extended Abstracts
Teddy Seyed, Peli de Halleux, Michal Moskal, James Devine, Joe Finney, Steve Hodges, Thomas Ball
2018 B conf
LCTES
James Devine, Joe Finney, Peli de Halleux, Michal Moskal, Thomas Ball, Steve Hodges
2007 Misc conf
CATA
John M. Weiss, James Devine, Andrew Detwiler
redb/extractors/decompiler/_archive/GhidraDecompilerScript-latest.java
← Index redb/extractors/decompiler/_archive/GhidraDecompilerScript-latest.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 {
        // 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];

        // 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);
        }

        // 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) {
        Address entry = function.getEntryPoint();
        String functionName = function.getName();
        String functionAddress = entry.toString();

        // Process decompiled code
        processDecompiledCode(function, output.getJSONArray("decompiled"), 
                            functionName, functionAddress);

        // Process disassembled code
        processDisassembledCode(function, output.getJSONArray("disassembled"), 
                              functionName, functionAddress);

        // Process CFG
        processCFG(function, output.getJSONArray("cfg"), functionAddress);
    }

    private void processDecompiledCode(Function function, JSONArray decompArray, 
                                     String functionName, String functionAddress) {
        DecompileResults results = decompInterface.decompileFunction(function, 30, monitor);
        if (results.decompileCompleted()) {
            String decompiledCode = results.getDecompiledFunction().getC();
            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);
        }
    }

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

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

            while (instructions.hasNext()) {
                try {
                    Instruction instr = instructions.next();
                    String disasmLine = instr.toString();
                    disassembly.append(disasmLine).append("\n");
                    normalized.append(normalizeInstruction(disasmLine)).append("\n");
                    instructionCount++;
                } catch (Exception e) {
                    System.err.println("Error processing instruction in " + functionName + ": " + e.getMessage());
                }
            }

            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);

            // Set similarity-related fields to null for now
            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);
        } catch (Exception e) {
            System.err.println("Error processing disassembly for " + functionName + ": " + e.getMessage());
        }
    }

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

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

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

                // Get successor blocks
                CodeBlockReferenceIterator successors = block.getDestinations(monitor);
                JSONArray successorAddresses = new JSONArray();
                while (successors.hasNext()) {
                    CodeBlockReference ref = successors.next();
                    successorAddresses.put(ref.getDestinationAddress().toString());
                }
                blockObj.put("successor_blocks", successorAddresses);

                cfgArray.put(blockObj);
            }
        } catch (Exception e) {
            System.err.println("{\"error\": \"Error processing CFG: " + 
                             e.getMessage().replace("\"", "'") + "\"}");
        }
    }

    private String normalizeInstruction(String instruction) {
        return instruction.replaceAll("0x[0-9a-fA-F]+", "IMM")
                        .replaceAll("\\b\\d+\\b", "NUM");
    }

    private String getBlockInstructions(CodeBlock block) {
        StringBuilder instructions = new StringBuilder();
        AddressIterator addresses = block.getAddresses(true);
        while (addresses.hasNext()) {
            Address addr = addresses.next();
            Instruction instr = currentProgram.getListing().getInstructionAt(addr);
            if (instr != null) {
                instructions.append(instr.toString()).append("\n");
            }
        }
        return instructions.toString();
    }

    private String calculateHash(String content) {
        try {
            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("{\"error\": \"Error calculating hash\"}");
            return "";
        }
    }
}