> For the complete documentation index, see [llms.txt](https://docs.hex-rays.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hex-rays.com/core/idalib/how-tos/malware-analysis-with-idalib.md).

# Malware analysis with Claude Code and idalib

This tutorial demonstrates a simple agentic use of idalib. [Claude Code on the Web](https://code.claude.com/docs/en/claude-code-on-the-web) inspects malware files in its sandbox, taking a plain-language prompt and driving the entire session: installing IDA, writing analysis scripts, running them against a binary, and extracting findings.

New to idalib? See the [Overview](/core/idalib/overview.md) first.

## Prerequisites

* An active IDA Pro license or IDA Home
* [Claude Code on the Web](https://code.claude.com/docs/en/web-quickstart), with connected GitHub repository (or another AI coding assistant that can write and run scripts)
* API Key created:
  * via HCLI by using `hcli auth key create`
  * via [Hex-Rays portal](https://my.hex-rays.com/dashboard/account-settings/api-keys)

**Optional**

* [Hex-Rays Claude Code skills](https://github.com/HexRaysSA/claude-marketplace): pre-built skills that teach Claude to work with idalib

## Walkthrough

### 0. Set up the cloud environment

In [Claude Code on the Web](https://claude.ai/code), choose your project's repository and add a cloud environment. Configure it with the following settings so that Claude can install IDA and idalib in the cloud sandbox using [HCLI](https://hcli.docs.hex-rays.com/):

* **Network access**: `Full`
* **Environment variables**:

```
HCLI_API_KEY=your-hcli-key
```

* **Setup script**:

```
#!/bin/bash
uv tool install ida-hcli
pip install --user ida-domain

```

![New cloud environment](/files/EvZkJp0NeHMxQOSpxvlu)

### 1. Get the sample

Prepare some known malware sample. This example uses the **Practical Malware Analysis Lab 01-01.dll**, a 32-bit Windows PE DLL from the [Mandiant capa test files repository](https://github.com/mandiant/capa-testfiles).

### 2. Give Claude Code a prompt

Open Claude Code on the Web and give it a plain-language prompt, for example:

*"Install IDA Pro and idalib with HCLI, then download `<URL to your malware sample>` and demonstrate you can analyze it with idalib, using the script. For reference, use <https://ida-domain.docs.hex-rays.com/llms.txt>"*

### 3. Review the analysis script

Claude Code writes an idalib script on the fly in response to the prompt. It uses standard IDAPython modules or the Domain API, depending on the prompt, to open the binary, wait for auto-analysis to complete, and extract segments, exports, imports, functions, and strings.

<details>

<summary>Exemplary script</summary>

```python
#!/usr/bin/env python3
"""
Analyze a PE binary with idalib via the ida-domain API.

Reference: https://ida-domain.docs.hex-rays.com/llms.txt

Usage:
    python analyze.py <path-to-binary>
"""

import sys
from ida_domain import Database


def banner(title):
    print()
    print("=" * 70)
    print(title)
    print("=" * 70)


def main(path):
    # Open the target; run auto-analysis, don't write an .idb back out.
    with Database.open(path=path, save_on_close=False) as db:
        md = db.metadata

        banner("FILE METADATA")
        print(f"  Path         : {db.path}")
        print(f"  Format       : {db.format}")
        print(f"  Architecture : {db.architecture}")
        print(f"  Bitness      : {db.bitness}-bit")
        print(f"  Base address : {hex(db.base_address)}")
        print(f"  Address range: {hex(db.minimum_ea)} - {hex(db.maximum_ea)}")
        print(f"  File size    : {db.filesize} bytes")
        print(f"  MD5          : {db.md5}")
        print(f"  SHA256       : {db.sha256}")
        print(f"  CRC32        : {hex(db.crc32)}")

        banner("SEGMENTS")
        for seg in db.segments:
            name = db.segments.get_name(seg)
            size = db.segments.get_size(seg)
            print(f"  {name:<10} {hex(seg.start_ea)}-{hex(seg.end_ea)}  "
                  f"size={size}")

        banner("ENTRY POINTS / EXPORTS")
        entries = list(db.entries.get_all())
        print(f"  {len(entries)} entry point(s)")
        for e in entries:
            ordinal = f"ord {e.ordinal}" if e.ordinal else "-"
            print(f"  {hex(e.address)}  {ordinal:<8}  {e.name}")

        banner("FUNCTIONS")
        funcs = list(db.functions.get_all())
        print(f"  {len(funcs)} function(s) recovered")
        for f in funcs:
            name = db.functions.get_name(f)
            size = f.end_ea - f.start_ea
            print(f"  {hex(f.start_ea)}  size={size:<5}  {name}")

        banner("IMPORTS (by module)")
        modules = list(db.imports.get_all_modules())
        total_imports = 0
        for mod in modules:
            imps = list(db.imports.get_imports_for_module(mod.index))
            total_imports += len(imps)
            print(f"\n  [{mod.name}] - {len(imps)} import(s)")
            for imp in imps:
                nm = imp.name or f"ordinal_{imp.ordinal}"
                print(f"    {hex(imp.address)}  {nm}")
        print(f"\n  Total: {total_imports} imports across {len(modules)} module(s)")

        banner("STRINGS")
        strings = list(db.strings.get_all())
        print(f"  {len(strings)} string(s) found. Showing all:")
        for s in strings:
            print(f"  {hex(s.address)}  {str(s)!r}")

        banner("ANALYSIS SUMMARY")
        print(f"  {len(funcs)} functions, {total_imports} imports, "
              f"{len(strings)} strings, {len(entries)} entry point(s).")
        # Simple behavioral hint: surface network-related imports.
        net_apis = {"socket", "WSAStartup", "connect", "send", "recv",
                    "gethostbyname", "InternetOpen", "InternetConnect",
                    "CreateProcess", "CreateService", "sleep", "Sleep"}
        seen = []
        for imp in db.imports.get_all_imports():
            if imp.name and imp.name in net_apis:
                seen.append(imp.name)
        if seen:
            print(f"  Notable APIs: {', '.join(sorted(set(seen)))}")


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"usage: {sys.argv[0]} <binary>", file=sys.stderr)
        sys.exit(2)
    main(sys.argv[1])
```

</details>

### 4. Run the analysis and review the output

Claude Code runs the script directly against the sample and produces the output.

<details>

<summary>Exemplary output</summary>

```

======================================================================
FILE METADATA
======================================================================
  Path         : /root/malware-analysis/Lab01-01.dll
  Format       : Portable executable for 80386 (PE)
  Architecture : metapc
  Bitness      : 32-bit
  Base address : 0x10000000
  Address range: 0x10001000 - 0x10027000
  File size    : 163840 bytes
  MD5          : 290934c61de9176ad682ffdd65f0a669
  SHA256       : f50e42c8dfaab649bde0398867e930b86c2a599e8db83b8260393082268f2dba
  CRC32        : 0xc414045d

======================================================================
SEGMENTS
======================================================================
  .text      0x10001000-0x10002000  size=4096
  .idata     0x10002000-0x1000205c  size=92
  .rdata     0x1000205c-0x10026000  size=147364
  .data      0x10026000-0x10027000  size=4096

======================================================================
ENTRY POINTS / EXPORTS
======================================================================
  1 entry point(s)
  0x100012fa  ord 268440314  DllEntryPoint

======================================================================
FUNCTIONS
======================================================================
  8 function(s) recovered
  0x10001000  size=13     sub_10001000
  0x10001010  size=490    _DllMain@12
  0x10001200  size=6      sub_10001200
  0x10001210  size=6      sub_10001210
  0x10001220  size=47     __alloca_probe
  0x1000124f  size=171    __CRT_INIT@12
  0x100012fa  size=157    DllEntryPoint
  0x10001398  size=6      _initterm

======================================================================
IMPORTS (by module)
======================================================================

  [KERNEL32] - 5 import(s)
    0x10002000  Sleep
    0x10002004  CreateProcessA
    0x10002008  CreateMutexA
    0x1000200c  OpenMutexA
    0x10002010  CloseHandle

  [WS2_32] - 10 import(s)
    0x1000204c  closesocket
    0x1000203c  connect
    0x10002054  htons
    0x10002038  inet_addr
    0x10002048  recv
    0x10002040  send
    0x10002044  shutdown
    0x10002030  socket
    0x10002034  WSAStartup
    0x10002050  WSACleanup

  [MSVCRT] - 5 import(s)
    0x10002018  _adjust_fdiv
    0x1000201c  malloc
    0x10002020  _initterm
    0x10002024  free
    0x10002028  strncmp

  Total: 20 imports across 3 module(s)

======================================================================
STRINGS
======================================================================
  16 string(s) found. Showing all:
  0x1000210a  'CloseHandle'
  0x10002118  'Sleep'
  0x10002120  'CreateProcessA'
  0x10002132  'CreateMutexA'
  0x10002142  'OpenMutexA'
  0x1000214e  'KERNEL32.dll'
  0x1000215c  'WS2_32.dll'
  0x1000216a  'strncmp'
  0x10002172  'MSVCRT.dll'
  0x10002188  '_initterm'
  0x10002194  'malloc'
  0x1000219e  '_adjust_fdiv'
  0x10026018  'sleep'
  0x10026020  'hello'
  0x10026028  '127.26.152.13'
  0x10026038  'SADFHUHF'

======================================================================
ANALYSIS SUMMARY
======================================================================
  8 functions, 20 imports, 16 strings, 1 entry point(s).
  Notable APIs: Sleep, WSAStartup, connect, recv, send, socket

```

</details>

### What this reveals

In this example, the strings and imports tell the story: `127.26.152.13` is a hardcoded C2 IP, `SADFHUHF` is a mutex name used to prevent re-infection, and the WS2\_32 imports confirm raw TCP socket communication. This is a classic backdoor from the Practical Malware Analysis lab series.

## What's next

For a broader look at the available approaches, see [Agentic IDA with idalib](/core/idalib/concepts/agentic-ida-with-idalib.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.hex-rays.com/core/idalib/how-tos/malware-analysis-with-idalib.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
