Troubleshooting

Common failure modes and debugging checklists

Common failure modes and debugging checklists.

Agent Not Calling Back

Symptoms: Implant deployed on target, no session appears in the operator console.

Checklist:

  1. Server running?

    # Check the server is listening
    ss -tlnp | grep 8443
  2. Correct server IP and port?

    • Check what was passed to -s (server) and -p (port) in the build command or Web UI
    • If using a redirector: the agent’s server should point to the redirector, not the C2
  3. Redirector forwarding correctly?

    # Test from the redirector host
    curl -k https://localhost:8443/api/poll/test
    # Should return 404 or a JSON error, not a connection refused
  4. Firewall blocking?

    • Check the target’s outbound firewall: can it reach the redirector on port 443/8443?
    • Check the C2’s inbound firewall: is port 8443 open to the redirector IP?
  5. TLS certificate issues?

    • Self-signed certs work (Schannel is configured to skip validation)
    • But if using a redirector with nginx, make sure nginx has valid certs configured
  6. Traffic profile mismatch?

    • If the implant was built with --profile slack but the redirector isn’t configured for Slack URIs, the redirector will reject the requests
    • Verify the server’s active profile matches the implant’s --profile and the redirector config
  7. Agent killed by EDR?

    • Check if the process is still running on the target
    • Try building without evasion flags first to isolate the issue
    • Try the --format service or --format dll delivery method
  8. DNS transport: NS records correct?

    • Verify: dig NS c2.example.com — should return your DNS server
    • Verify: dig TXT test.c2.example.com @<YOUR_DNS_SERVER> — should get a response

BOF Crashes

Symptoms: Agent stops responding after running a specific BOF, or BOF returns no output.

Common causes:

  1. Wrong arguments: Some BOFs require specific argument formats. Check the BOF Reference for usage.

  2. Privilege insufficient: BOFs like hashdump, nanodump, getsystem_token require admin/SYSTEM privileges. Check with whoami first.

  3. Target process doesn’t exist: Injection BOFs (createremotethread, steal_token) need a valid PID. Verify with ps first.

  4. BOF binary missing: The BOF .o file must be in the bofs/ directory. Rebuild:

    cd bofs/ && ./build-bof.sh <bofname>
  5. Agent crashed: If the agent stops responding entirely, the BOF likely crashed the process. Redeploy the implant and avoid that BOF (or fix it).

Migration Failures

Symptoms: migrate command hangs or agent goes dark.

Debugging:

  1. Target process alive? Check ps output for the target PID.

  2. Target process architecture? Must be x64. Migration to x86 (WoW64) processes will fail.

  3. Protected process? Don’t migrate to lsass.exe, csrss.exe, smss.exe, or other PPL-protected processes.

  4. Already migrated? Each migration creates a new agent. The old agent is still alive unless you exit it.

  5. EDR blocked injection? Try a different injection technique:

    # Rebuild with context hijack instead of default APC
    krait> build windows -s <IP> -p 8443 --context-hijack ...

Execute-Assembly Failures

Symptoms: execute-assembly returns no output or the agent hangs.

Checklist:

  1. Assembly file exists? The path is resolved on the operator host, then uploaded to the agent.

  2. .NET version: Krait hosts CLR v4 (supports .NET Framework 4.x assemblies). .NET Core/.NET 5+ assemblies won’t work.

  3. Assembly arguments: Make sure arguments are passed correctly:

    execute-assembly /opt/Seatbelt.exe -group=all
  4. Output capture: If using Bitdefender-safe mode (execute-assembly-noeva), output capture uses AllocConsole + SetStdHandle. Some assemblies may not produce output if they write to a different stream.

  5. LoadLibrary proxy issues: If --loadlib-proxy is enabled and the assembly loads an unusual DLL that the manual mapper can’t handle, the fallback to original LdrLoadDll should kick in. If the assembly still fails, rebuild without --loadlib-proxy.

TLS Handshake Issues

Symptoms: Agent connects but immediately disconnects, or connection resets.

  1. Protocol mismatch: Krait uses TLS 1.2. If the server or redirector only accepts TLS 1.3, the handshake will fail.

  2. SNI mismatch: If using nginx with server_name, the implant must connect to a hostname that matches (not an IP).

  3. Certificate chain: Schannel skips certificate validation by default (SCH_CRED_MANUAL_CRED_VALIDATION), so certificate issues shouldn’t cause failures. But nginx may require a complete certificate chain.

SOCKS Proxy Issues

Symptoms: SOCKS proxy starts but proxychains connections time out.

  1. Port in use? Check if the SOCKS port is already bound:

    ss -tlnp | grep 1080
  2. Proxychains configured? Edit /etc/proxychains4.conf:

    socks5 127.0.0.1 1080
  3. Agent still alive? SOCKS traffic flows through the agent. If the agent sleeps, SOCKS pauses. Use a short interval when SOCKS is active.

  4. Target reachable? The SOCKS proxy routes through the agent — the target must be reachable from the agent’s network position.

Server Startup Issues

  1. Port already in use:

    ss -tlnp | grep 8443
    # Kill the existing process or use a different port
  2. BOFs directory not found:

    [!] BOFs directory not found: bofs/

    Make sure you’re running from the release directory root where the bofs/ folder exists.

CLI Connection Issues

  1. Server not reachable:

    [!] Cannot connect to 127.0.0.1:50051

    Check that the server is running and the API port is correct.

  2. Authentication failed:

    [!] Authentication failed

    Check the username and password. Operator accounts are in operator/operators.json.

  3. No operators configured: If operators.json doesn’t exist or is empty, the server runs in legacy single-operator mode (no auth). Create accounts with ./server/krait-server operator add <name>.

Debugging Tips

  • Event log: The log command shows timestamped events including registrations, task dispatches, results, and errors. Start here.
  • Timeline: The timeline command shows events in chronological order — useful for correlating agent behavior with operator actions.
  • Results: The results command shows raw task output. If a BOF returned data but the console didn’t display it, check results directly.
  • Verbose server: Run the server in foreground (not as a systemd service) to see Python tracebacks and debug output.