IDASQL: SQL Interface for IDA Pro

repository·main·Indexed 43 days ago

https://github.com/allthingsida/idasql

A SQL interface for IDA Pro that maps internal structures to over 30 virtual tables, enabling developers and AI agents to query and modify IDA databases using standard SQL. It supports a standalone CLI, an IDA plugin, and AI-driven skill workflows for tools like Claude and ChatGPT. Key capabilities include disassembly and decompiler queries, type recovery, and database annotations without requiring IDAPython scripts.

Tokens
27.1K
Snippets
63
Records
97
Agent score
57%

What's inside IDASQL

  1. Overview of IDASQL

    main

    IDASQL provides a SQL interface for IDA Pro databases, allowing users and AI agents to interact with compiled binaries using standard SQL queries instead of IDAPython. It exposes over 30 virtual tables covering functions, cross-references, strings, types, imports, disassembly, and decompilation.

    Key features include:

    • No indexing required: Queries run directly against the live IDA database.
    • Read and Write: Beyond querying, IDASQL allows modifying the database, including adding decompilation comments, performing type recovery, applying structure/union offsets, and updating function prototypes.
    • Agent-Agnostic: Works with any tool capable of issuing SQL, such as Claude, ChatGPT, Copilot, or Cursor.
    • Flexible Modes: Supports Standalone CLI, IDA Plugin (GUI), and Skill Workflows (AI-driven).
  2. Using the Hex-Rays decompiler in IDASQL

    main

    The Hex-Rays decompiler converts assembly into C-like pseudocode. There are two primary ways to interact with decompiled code via SQL:

    1. Full Function Display (Primary Read Surface)

    Use the decompile(addr) function to get the entire function as a single text block. Each line is prefixed with an address anchor (e.g., /* 401010 */) or a placeholder (/* */) if no anchor exists. This is the preferred method for explaining function logic.

    2. Structured Editing (Edit Surface)

    Use the pseudocode table for line-level operations. This table allows for filtering by func_addr, addr, or line_num and is used for writing comments.

    3. AST-level Analysis

    For deep structural analysis, use:

    • ctree: The Abstract Syntax Tree of the decompiled code.
    • ctree_call_args: Information about call arguments within the AST.
    • ctree_lvars: Used to rename, change types, or add comments to local variables.
    -- Primary way to view code
    SELECT decompile('DriverEntry');
  3. Use Decompiler tables for structured analysis (Hex-Rays Required)

    main

    If Hex-Rays is available, you can query the AST and pseudocode via specialized tables.

    CRITICAL PERFORMANCE NOTE: Always filter by func_addr. Without a constraint, the engine will attempt to decompile every function in the binary, which is extremely slow.

    Key Tables

    • pseudocode: Line-by-line pseudocode. Use decompile(addr) for viewing; use this table for surgical comment edits. Writable columns include comment and comment_placement (e.g., semi, block1, brace1, etc.).
    • ctree: The full AST of decompiled code. Filter by func_addr.
    • ctree_lvars: Local variables. Writable: name, type, comment. Filter by func_addr and update via idx.
    • ctree_call_args: Flattened call arguments for easy joining.

    Decompiler Views

    Pre-built views for common patterns:

    • ctree_v_calls: Function calls with callee info.
    • ctree_v_loops: for/while/do loops.
    • ctree_v_ifs: if statements.
    • ctree_v_returns: Return statements with classification (e.g., return_num, return_var).
  4. Understand the xsql family of tools

    main

    IDASQL is part of the xsql family, a collection of tools that expose various binary-analysis and debug-information platforms through a unified SQL interface. All these tools are built on the shared libxsql virtual-table framework, meaning SQL queries learned for one tool (e.g., SELECT name, size FROM funcs ORDER BY size DESC LIMIT 10) are largely portable across the entire family.

    Tool Categories

    Reverse-engineering platforms:

    • bnsql: Binary Ninja databases as SQL.
    • ghidrasql: Ghidra databases as SQL.

    Debug info & compiler data:

    • pdbsql: Windows PDB symbol files as SQL.
    • dwarfsql: DWARF debug information as SQL.
    • clangsql: Clang AST as SQL.

    Core:

    • libxsql: The underlying C++ SQLite virtual-table framework.
  5. Understanding Cross-References (xrefs)

    main

    Cross-references (xrefs) represent relationships between addresses in the binary, such as function calls, jumps, or data references.

    The xrefs table: Use the table xrefs(from_addr, to_addr, type, is_code, from_func) to map these relationships.

    • from_addr → to_addr indicates that address X references address Y.
    • Important: This table contains real references only. It excludes ordinary fall-through flow edges (e.g., a simple instruction-to-next-instruction sequence) to ensure counts reflect actual calls, jumps, or data references.
  6. Querying functions and their properties

    main

    Functions in IDA are groups of code defined by a start address, end address, name, and size. You can query function metadata directly from the database.

    Function attributes:

    • addr / start_addr: The beginning of the function.
    • end_addr: The end of the function.
    • name: The assigned or auto-generated name (e.g., main).
    • size: Total byte count of the function.

    Note: For single-address disassembly (code or data) that may not belong to a function, use disasm_at(addr[, context]) instead of function-scoped queries.

  7. Analyzing Basic Blocks

    main

    A basic block is a straight-line sequence of code with a single entry point and a single exit point, containing no internal branches. These are essential for control flow analysis.

    Use the blocks table to retrieve them: blocks(start_addr, end_addr, func_addr, size)

  8. How to start IDASQL in different modes

    main

    IDASQL can be operated in three distinct modes depending on your workflow:

    1. Standalone CLI: Best for direct SQL execution, scripting, and automated pipelines. Use the -s flag to specify the binary and -i for interactive mode.
    2. IDA Plugin: Best for working inside the IDA GUI. Select idasql from the IDA CLI dropdown.
    3. Skill Workflow: Best for AI-driven analysis. Use /idasql:connect in your coding agent's CLI to allow the agent to issue SQL queries autonomously.
    # Standalone CLI example
    $ idasql -s WerFaultTool.exe.i64 -q "SELECT * FROM funcs LIMIT 5"
  9. How to use addresses (ea_t) in IDASQL

    main

    In IDASQL, addresses (effective addresses or ea_t) are represented as unsigned 64-bit integers. When querying, you can use integer EAs, numeric strings, or global symbol names.

    Key behaviors:

    • Symbol Resolution: Symbol names (e.g., 'DriverEntry') are resolved using get_name_ea. If a symbol cannot be resolved, the error Could not resolve name to address: <name> is returned.
    • Formatting: For human-readable hex display in results, use printf('0x%X', addr).
    • Predicates: Use standard SQL WHERE clauses to filter by address (e.g., WHERE addr = 0x401000).
    -- Using a symbol name
    SELECT decompile('DriverEntry');
    
    -- Using a numeric string for an update
    UPDATE applied_types
    SET decl = 'NTSTATUS DriverEntry(PDRIVER_OBJECT, PUNICODE_STRING);'
    WHERE addr = 'DriverEntry';
    
    -- Using an integer EA
    SELECT (SELECT comment FROM comments WHERE addr = 0x401000 LIMIT 1);
  10. Managing memory segments

    main

    Memory is organized into segments (e.g., .text for code, .data for initialized data, .rdata for read-only data, and .bss for uninitialized data). You can query and modify the memory layout using the segments table.

    The segments table: segments(start_addr, end_addr, name, class, perm)

    Writable columns:

    • UPDATE segments SET start_addr = ... can be used to rebase (move) a segment.
    • UPDATE segments SET end_addr = ... can be used to resize a segment.
  11. Work with multiple databases simultaneously

    main
    IDASQL allows you to open and query multiple databases at once. This enables cross-referencing, comparing, and transferring annotations between different binaries. You can instruct an AI agent to open multiple files in the background and perform comparative analysis, such as finding common strings across multiple .exe files.
  12. Use Common Table Expressions (CTEs) for complex binary analysis

    main

    CTEs allow you to create readable, modular queries and perform recursive traversals like call graph analysis.

    Basic CTE for Filtering

    You can use CTEs to isolate specific behaviors (e.g., finding functions that call malloc and also perform a null check) before joining them.

    Recursive CTEs for Call Graph Traversal

    Recursive CTEs are essential for traversing call graphs. You can use them to:

    • Forward Traversal: Find all functions reachable from a starting point (e.g., main) up to a specific depth.
    • Reverse Traversal: Find all transitive callers of a specific target address.

    CTE with Aggregation

    Use CTEs to pre-calculate metrics like call counts or block counts per function, then join them to the funcs table to rank functions by complexity.

    -- Find all functions reachable from main (up to depth 5)
    WITH RECURSIVE call_graph AS (
        -- Base case: start from main
        SELECT addr as func_addr, name, 0 as depth
        FROM funcs WHERE name = 'main'
    
        UNION ALL
    
        -- Recursive case: follow calls
        SELECT f.addr, f.name, cg.depth + 1
        FROM call_graph cg
        JOIN disasm_calls dc ON dc.func_addr = cg.func_addr
        JOIN funcs f ON f.addr = dc.callee_addr
        WHERE cg.depth < 5
          AND dc.callee_addr != 0  -- Skip indirect calls
    )
    SELECT DISTINCT func_addr, name, MIN(depth) as min_depth
    FROM call_graph
    GROUP BY func_addr
    ORDER BY min_depth, name;