Skip to main content

Overview

Dr.Semu generates multiple JSON files during analysis, each containing different types of information about the analyzed sample.

Report Files

A complete analysis report directory contains:
  • starter.json - Metadata about the initial process
  • {pid}.json - Dynamic analysis for each process
  • {sha256}.json - Static analysis for each executable

starter.json

Contains metadata about the initial analyzed process.
{
    "empty": false,
    "image_path": "C:\\path\\to\\sample.exe",
    "starter_pid": 1234,
    "sha_256": "abc123..."
}
empty
boolean
required
Indicates whether the starter process data is empty. If true, analysis did not complete successfully.
image_path
string
Full path to the executable that was analyzed
starter_pid
integer
Process ID of the initial process
sha_256
string
SHA-256 hash of the analyzed executable. Use this to locate the corresponding static analysis file.

Dynamic Analysis (.json)

Contains logged Windows API calls for a specific process. The file is an array of API call objects.
[
    {
        "NtCreateUserProcess": {
            "success": true,
            "before": {
                "image_path": "C:\\Windows\\System32\\whoami.exe",
                "command_line": "whoami.exe"
            },
            "after": {
                "proc_id": 5678
            }
        }
    },
    {
        "NtCreateKey": {
            "success": true,
            "before": {
                "key_path": "HKCU\\Software\\Malicious"
            }
        }
    }
]
empty
boolean
Present in some cases to indicate if the process data is empty
Each array element represents a single API call with the following structure:

API Call Object

{FunctionName}
object
The Windows API function name (e.g., NtCreateUserProcess, NtCreateKey)
success
boolean
required
Indicates whether the API call completed successfully
before
object
Parameters and state before the API call execution. Fields vary by function.
after
object
Results and state after the API call execution. Fields vary by function.

Static Analysis (.json)

Contains PE file information and static analysis results.
{
    "generic": {
        "is_x86": true,
        "is_dll": false,
        "machine_type": "x86"
    }
}
generic
object
required
Generic PE file information
is_x86
boolean
Indicates if the file is a 32-bit (x86) executable
is_dll
boolean
Indicates if the file is a DLL
machine_type
string
CPU architecture (e.g., “x86”, “x64”)

Common API Functions

These are the most frequently encountered Windows API calls in dynamic analysis:

NtCreateUserProcess

Process creation and execution.
before.image_path
string
Path to the executable being launched
before.command_line
string
Command line arguments
after.proc_id
integer
Process ID of the newly created process. Use with utils.get_json_pid() (Lua) or to construct the path to the process’s JSON file (Python).
Example:
{
    "NtCreateUserProcess": {
        "success": true,
        "before": {
            "image_path": "C:\\Windows\\System32\\cmd.exe",
            "command_line": "cmd.exe /c whoami"
        },
        "after": {
            "proc_id": 2468
        }
    }
}

NtCreateKey

Registry key creation.
before.key_path
string
Full registry key path being created
Example:
{
    "NtCreateKey": {
        "success": true,
        "before": {
            "key_path": "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
        }
    }
}

NtSetValueKey

Registry value modification.
before.key_path
string
Registry key path
before.value_name
string
Name of the registry value
before.data
string
Data being written to the registry value

NtCreateFile

File creation or opening.
before.file_path
string
Path to the file being created or opened
before.access_mask
integer
Requested access rights

NtWriteFile

File write operation.
before.file_handle
integer
Handle to the file
before.buffer
string
Data being written (may be truncated or encoded)

Working with Child Processes

When a process creates child processes, you can analyze them by:
  1. Finding NtCreateUserProcess calls with success: true
  2. Extracting the after.proc_id value
  3. Loading the corresponding {proc_id}.json file
Lua Example:
if win_func.NtCreateUserProcess.success == true then
    local target_PID = win_func.NtCreateUserProcess.after.proc_id
    local child_json = utils.get_json_pid(report_directory, target_PID)
    if not child_json.empty then
        -- Analyze child process calls
    end
end
Python Example:
if "NtCreateUserProcess" in win_func:
    if win_func["NtCreateUserProcess"]["success"]:
        child_pid = win_func["NtCreateUserProcess"]["after"]["proc_id"]
        child_json_path = report_directory + b"\\" + str(child_pid).encode() + b".json"
        child_data = dr_semu_utils.get_json_from_file(child_json_path)
        # Analyze child process calls

File Naming Convention

  • Dynamic analysis: {pid}.json where pid is the process ID (e.g., 1234.json)
  • Static analysis: {sha256}.json where sha256 is the full SHA-256 hash (e.g., abc123def456...789.json)
  • Starter metadata: Always named starter.json

Best Practices

  1. Check empty flag: Always verify empty is false before processing data
  2. Verify success: Check the success field before accessing API call results
  3. Handle missing fields: Not all API calls include all fields; check for existence before accessing
  4. Track process tree: Use PIDs from NtCreateUserProcess to build a complete process execution tree
  5. Combine static and dynamic: Use both static PE information and dynamic behavior for accurate detection

Build docs developers (and LLMs) love