jpskill.com
🛠️ 開発・MCP コミュニティ

binary-re-dynamic-analysis

QEMUエミュレーター、GDBデバッガー、Fridaフッキングなどのツールを使い、バイナリ実行時の挙動を追跡・分析し、システムコールやメモリの状態を監視、関数を横取りするなど、プログラムの動的な解析を行うSkill。

📜 元の英語説明(参考)

Use when you need to run a binary, trace execution, or observe runtime behavior. Runtime analysis via QEMU emulation, GDB debugging, and Frida hooking - syscall tracing (strace), breakpoints, memory inspection, function interception. Keywords - "run binary", "execute", "debug", "trace syscalls", "set breakpoint", "qemu", "gdb", "frida", "strace", "watch memory"

🇯🇵 日本人クリエイター向け解説

一言でいうと

QEMUエミュレーター、GDBデバッガー、Fridaフッキングなどのツールを使い、バイナリ実行時の挙動を追跡・分析し、システムコールやメモリの状態を監視、関数を横取りするなど、プログラムの動的な解析を行うSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o binary-re-dynamic-analysis.zip https://jpskill.com/download/16694.zip && unzip -o binary-re-dynamic-analysis.zip && rm binary-re-dynamic-analysis.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/16694.zip -OutFile "$d\binary-re-dynamic-analysis.zip"; Expand-Archive "$d\binary-re-dynamic-analysis.zip" -DestinationPath $d -Force; ri "$d\binary-re-dynamic-analysis.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して binary-re-dynamic-analysis.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → binary-re-dynamic-analysis フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

動的解析 (フェーズ 4)

目的

実際の実行時の挙動を観察します。静的解析からの仮説を検証します。実行中にのみ見えるデータをキャプチャします。

ヒューマン・イン・ザ・ループの要件

重要: すべての実行には人間の承認が必要です。

任意のバイナリを実行する前に:

  1. サンドボックス構成が許容範囲内であることを確認します
  2. 必要な場合は、ネットワーク分離を検証します
  3. 実行が試みる内容を文書化します
  4. 明示的な承認を得ます

プラットフォームサポートマトリックス

ホストプラットフォーム ターゲットアーキテクチャ 方法 複雑さ
Linux x86_64 ARM32/64, MIPS ネイティブ qemu-user
Linux x86_64 x86-32 ネイティブまたは linux32
macOS (任意) ARM32/64 Docker + binfmt
macOS (任意) x86-32 Docker --platform linux/i386
Windows 任意 WSL2 → Linux メソッド

macOS Docker セットアップ (初回のみ)

# Docker ランタイムを起動 (Colima, Docker Desktop など)
colima start

# ARM エミュレーションハンドラを登録 (特権モードが必要)
docker run --rm --privileged --platform linux/arm64 \
  tonistiigi/binfmt --install arm

Docker マウントのベストプラクティス

重要: Colima では、/tmp マウントはサイレントに失敗することがよくあります。常にホームディレクトリのパスを使用してください。

# ✅ 良い例 - ホームディレクトリを使用
docker run -v ~/code/samples:/work:ro ...

# ❌ 悪い例 - /tmp マウントは Colima で失敗する可能性があります
docker run -v /tmp/samples:/work:ro ...

解析オプション

方法 分離 粒度 最適な用途
QEMU -strace システムコールレベル 初期動作のマッピング
QEMU + GDB 命令レベル 詳細なデバッグ
Docker プロセスレベル macOS でのクロスアーキテクチャ
Frida 関数レベル 再コンパイルなしのフック
オンデバイス フルシステム エミュレーションが失敗した場合

オプション A: システムコールトレース付き QEMU ユーザーモード

最も安全なアプローチ - システムコールロギングで隔離された状態で実行されます。

セットアップ

# sysroot が存在することを確認
ls /usr/arm-linux-gnueabihf/lib/libc.so*

# ARM 32 ビット実行
qemu-arm -L /usr/arm-linux-gnueabihf -strace -- ./binary

# ARM 64 ビット実行
qemu-aarch64 -L /usr/aarch64-linux-gnu -strace -- ./binary

Sysroot の選択

バイナリ ABI Sysroot パス QEMU フラグ
ARM glibc hard-float /usr/arm-linux-gnueabihf -L
ARM glibc soft-float /usr/arm-linux-gnueabi -L
ARM64 glibc /usr/aarch64-linux-gnu -L
ARM musl カスタム抽出が必要 -L

環境制御

# 環境変数を設定
qemu-arm -L /sysroot \
  -E HOME=/tmp \
  -E USER=nobody \
  -E LD_DEBUG=bindings \
  -- ./binary

# 危険な変数を設定解除
qemu-arm -L /sysroot \
  -U LD_PRELOAD \
  -- ./binary

システムコール解析

監視する Strace 出力パターン:

# ネットワークアクティビティ
openat.*socket
connect(.*AF_INET
sendto\|send\|write.*socket
recvfrom\|recv\|read.*socket

# ファイルアクセス
openat.*O_RDONLY.*"/etc
openat.*O_WRONLY
stat\|lstat.*"/

# プロセス操作
execve
fork\|clone

オプション B: 詳細なデバッグのための QEMU + GDB

命令レベルの制御のためにデバッガをアタッチします。

GDB でのバイナリの起動

# GDB サーバーで QEMU を起動
qemu-arm -g 1234 -L /usr/arm-linux-gnueabihf ./binary &

# gdb-multiarch で接続
gdb-multiarch -q \
  -ex "set architecture arm" \
  -ex "target remote :1234" \
  -ex "source ~/.gdbinit-gef.py" \
  ./binary

RE 用の GDB コマンド

# ブレークポイント
break *0x8400              # アドレス
break main                 # シンボル
break *0x8400 if $r0 == 5  # 条件付き

# 実行制御
continue                   # ブレークまで実行
stepi                      # 単一命令
nexti                      # コールをステップオーバー
finish                     # リターンまで実行

# 検査
info registers             # すべてのレジスタ
x/20i $pc                  # PC から逆アセンブル
x/10wx $sp                 # スタックの内容
x/s 0x12345                # アドレスの文字列

# メモリ
find 0x8000, 0x10000, "pattern"  # メモリを検索
dump memory /tmp/mem.bin 0x8000 0x9000  # 領域を抽出

GEF の拡張機能

GEF をロードすると、追加のコマンド:

gef> vmmap                 # メモリレイアウト
gef> checksec              # セキュリティ機能
gef> context               # 完全な状態表示
gef> hexdump qword $sp 10  # より良いヘックスダンプ
gef> pcustom               # 構造体の定義

バッチデバッグスクリプト

# GDB スクリプトを作成
cat > analyze.gdb << 'EOF'
set architecture arm
target remote :1234
break main
continue
info registers
x/20i $pc
continue
quit
EOF

# バッチを実行
gdb-multiarch -batch -x analyze.gdb ./binary

オプション C: 関数フックのための Frida

バイナリを変更せずに、関数呼び出しをインターセプトします。

⚠️ アーキテクチャの制約: Frida はネイティブアーキテクチャでの実行が必要です。QEMU-user ターゲットにアタッチできません

シナリオ 動作しますか? 代替案
ネイティブバイナリ (x86_64 on x86_64) -
QEMU-user 下のクロスアーキテクチャ オンデバイス frida-server を使用
Docker ネイティブアーキテクチャコンテナ -
Docker クロスアーキテクチャ (エミュレート) オンデバイス frida-server を使用

クロスアーキテクチャ Frida の場合は、ターゲットデバイスに frida-server をデプロイします。

# ターゲットデバイス上:
./frida-server &

# ホスト上:
frida -H device:27042 -f ./binary -l hook.js --no-pause

基本的なフック

// hook_connect.js
Interceptor.attach(Module.findExportByName(null, "connect"), {
  onEnter: function(args) {
    console.log("[connect] Called");
    var sockaddr = args[1];
    var family = sockaddr.readU16();
    if (family == 2) { // AF_INET
      var port = sockaddr.add(2).readU16();
      var ip = sockaddr.add(4).readByteArray(4);
      console.log("  Port: " + ((port >> 8) | ((port & 0xff) << 8)));
      console.log("  IP: " + new Uint8Array(ip).join("."));
    }
  },
  onLeave: function(retval) {
    console.log("  Return: " + retval);
  }
});

# Frida で実行
f

(原文はここで切り詰められています)
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Dynamic Analysis (Phase 4)

Purpose

Observe actual runtime behavior. Verify hypotheses from static analysis. Capture data that's only visible during execution.

Human-in-the-Loop Requirement

CRITICAL: All execution requires human approval.

Before running ANY binary:

  1. Confirm sandbox configuration is acceptable
  2. Verify network isolation if required
  3. Document what execution will attempt
  4. Get explicit approval

Platform Support Matrix

Host Platform Target Arch Method Complexity
Linux x86_64 ARM32/64, MIPS Native qemu-user Low
Linux x86_64 x86-32 Native or linux32 Low
macOS (any) ARM32/64 Docker + binfmt Medium
macOS (any) x86-32 Docker --platform linux/i386 Medium
Windows Any WSL2 → Linux method Medium

macOS Docker Setup (One-Time)

# Start Docker runtime (Colima, Docker Desktop, etc.)
colima start

# Register ARM emulation handlers (requires privileged mode)
docker run --rm --privileged --platform linux/arm64 \
  tonistiigi/binfmt --install arm

Docker Mount Best Practices

CRITICAL: On Colima, /tmp mounts often fail silently. Always use home directory paths:

# ✅ GOOD - use home directory
docker run -v ~/code/samples:/work:ro ...

# ❌ BAD - /tmp mounts can fail on Colima
docker run -v /tmp/samples:/work:ro ...

Analysis Options

Method Isolation Granularity Best For
QEMU -strace High Syscall level Initial behavior mapping
QEMU + GDB High Instruction level Detailed debugging
Docker High Process level Cross-arch on macOS
Frida Medium Function level Hooking without recompilation
On-device Low Full system When emulation fails

Option A: QEMU User-Mode with Syscall Trace

Safest approach - runs in isolation with syscall logging.

Setup

# Verify sysroot exists
ls /usr/arm-linux-gnueabihf/lib/libc.so*

# ARM 32-bit execution
qemu-arm -L /usr/arm-linux-gnueabihf -strace -- ./binary

# ARM 64-bit execution
qemu-aarch64 -L /usr/aarch64-linux-gnu -strace -- ./binary

Sysroot Selection

Binary ABI Sysroot Path QEMU Flag
ARM glibc hard-float /usr/arm-linux-gnueabihf -L
ARM glibc soft-float /usr/arm-linux-gnueabi -L
ARM64 glibc /usr/aarch64-linux-gnu -L
ARM musl Custom extraction needed -L

Environment Control

# Set environment variables
qemu-arm -L /sysroot \
  -E HOME=/tmp \
  -E USER=nobody \
  -E LD_DEBUG=bindings \
  -- ./binary

# Unset dangerous variables
qemu-arm -L /sysroot \
  -U LD_PRELOAD \
  -- ./binary

Syscall Analysis

Strace output patterns to watch:

# Network activity
openat.*socket
connect(.*AF_INET
sendto\|send\|write.*socket
recvfrom\|recv\|read.*socket

# File access
openat.*O_RDONLY.*"/etc
openat.*O_WRONLY
stat\|lstat.*"/

# Process operations
execve
fork\|clone

Option B: QEMU + GDB for Deep Debugging

Attach debugger for instruction-level control.

Launch Binary Under GDB

# Start QEMU with GDB server
qemu-arm -g 1234 -L /usr/arm-linux-gnueabihf ./binary &

# Connect with gdb-multiarch
gdb-multiarch -q \
  -ex "set architecture arm" \
  -ex "target remote :1234" \
  -ex "source ~/.gdbinit-gef.py" \
  ./binary

GDB Commands for RE

# Breakpoints
break *0x8400              # Address
break main                 # Symbol
break *0x8400 if $r0 == 5  # Conditional

# Execution control
continue                   # Run until break
stepi                      # Single instruction
nexti                      # Step over calls
finish                     # Run until return

# Inspection
info registers             # All registers
x/20i $pc                  # Disassemble from PC
x/10wx $sp                 # Stack contents
x/s 0x12345                # String at address

# Memory
find 0x8000, 0x10000, "pattern"  # Search memory
dump memory /tmp/mem.bin 0x8000 0x9000  # Extract region

GEF Enhancements

With GEF loaded, additional commands:

gef> vmmap                 # Memory layout
gef> checksec              # Security features
gef> context               # Full state display
gef> hexdump qword $sp 10  # Better hex dump
gef> pcustom               # Structure definitions

Batch Debugging Script

# Create GDB script
cat > analyze.gdb << 'EOF'
set architecture arm
target remote :1234
break main
continue
info registers
x/20i $pc
continue
quit
EOF

# Run batch
gdb-multiarch -batch -x analyze.gdb ./binary

Option C: Frida for Function Hooking

Intercept function calls without modifying binary.

⚠️ Architecture Constraint: Frida requires native-arch execution. It cannot attach to QEMU-user targets.

Scenario Works? Alternative
Native binary (x86_64 on x86_64) -
Cross-arch under QEMU-user Use on-device frida-server
Docker native-arch container -
Docker cross-arch (emulated) Use on-device frida-server

For cross-arch Frida, deploy frida-server to the target device:

# On target device:
./frida-server &

# On host:
frida -H device:27042 -f ./binary -l hook.js --no-pause

Basic Hook

// hook_connect.js
Interceptor.attach(Module.findExportByName(null, "connect"), {
  onEnter: function(args) {
    console.log("[connect] Called");
    var sockaddr = args[1];
    var family = sockaddr.readU16();
    if (family == 2) { // AF_INET
      var port = sockaddr.add(2).readU16();
      var ip = sockaddr.add(4).readByteArray(4);
      console.log("  Port: " + ((port >> 8) | ((port & 0xff) << 8)));
      console.log("  IP: " + new Uint8Array(ip).join("."));
    }
  },
  onLeave: function(retval) {
    console.log("  Return: " + retval);
  }
});
# Run with Frida
frida -f ./binary -l hook_connect.js --no-pause

Tracing All Calls to Library

// trace_libcurl.js
var libcurl = Process.findModuleByName("libcurl.so.4");
if (libcurl) {
  libcurl.enumerateExports().forEach(function(exp) {
    if (exp.type === "function") {
      Interceptor.attach(exp.address, {
        onEnter: function(args) {
          console.log("[" + exp.name + "] called");
        }
      });
    }
  });
}

Memory Inspection

// dump_memory.js
var base = Module.findBaseAddress("binary");
console.log("Base: " + base);

// Dump region
var data = base.add(0x1000).readByteArray(256);
console.log(hexdump(data, { offset: 0, length: 256 }));

Option D: Docker-Based Cross-Architecture (macOS)

Use Docker for cross-arch execution when native QEMU unavailable.

ARM32 Binary on macOS

docker run --rm --platform linux/arm/v7 \
  -v ~/code/samples:/work:ro \
  arm32v7/debian:bullseye-slim \
  sh -c '
    # Fix linker path mismatch (common issue)
    ln -sf /lib/ld-linux-armhf.so.3 /lib/ld-linux.so.3 2>/dev/null || true

    # Install dependencies if needed (check rabin2 -l output)
    apt-get update -qq && apt-get install -qq -y libcap2 libacl1 2>/dev/null

    # Run with library debug output (strace alternative)
    LD_DEBUG=libs /work/binary args
  '

ARM64 Binary on macOS

docker run --rm --platform linux/arm64 \
  -v ~/code/samples:/work:ro \
  arm64v8/debian:bullseye-slim \
  sh -c 'LD_DEBUG=libs /work/binary args'

x86 32-bit Binary on macOS

docker run --rm --platform linux/i386 \
  -v ~/code/samples:/work:ro \
  i386/debian:bullseye-slim \
  sh -c '/work/binary args'

Tracing Limitations in Docker/QEMU User-Mode

Method Works? Alternative
strace ❌ (ptrace not implemented) LD_DEBUG=files,libs
ltrace ❌ (same reason) Direct observation or Frida
gdb ✓ (with QEMU -g flag) N/A

LD_DEBUG Options (strace alternative)

LD_DEBUG=libs     # Library search and loading
LD_DEBUG=files    # File operations during loading
LD_DEBUG=symbols  # Symbol resolution
LD_DEBUG=bindings # Symbol binding details
LD_DEBUG=all      # Everything (verbose)

Option E: On-Device Analysis

When emulation fails or device-specific behavior needed.

Remote GDB via gdbserver

# On target device (via SSH/ADB)
gdbserver :1234 ./binary

# On host (with port forward)
ssh -L 1234:localhost:1234 user@device &
gdb-multiarch -q \
  -ex "target remote localhost:1234" \
  ./binary

Remote strace (if available)

# On target device
strace -f -o /tmp/trace.log ./binary

# Pull log
scp user@device:/tmp/trace.log .

Sandbox Configuration

Minimal Sandbox (nsjail)

nsjail \
  --mode o \
  --chroot /sysroot \
  --user 65534 \
  --group 65534 \
  --disable_clone_newnet \
  --rlimit_as 512 \
  --time_limit 60 \
  -- /binary

QEMU with Resource Limits

# CPU time limit
timeout 60 qemu-arm -L /sysroot -strace ./binary

# Memory limit via cgroup (requires setup)
cgexec -g memory:qemu_sandbox qemu-arm -L /sysroot ./binary

Anti-Analysis Detection

Before dynamic analysis, check for common anti-debugging/anti-analysis patterns:

Static Detection (Pre-Execution)

# Check for anti-debug strings/imports
strings -a binary | grep -Ei 'ptrace|anti|debugger|seccomp|LD_PRELOAD|/proc/self'

# r2: Look for ptrace/prctl/seccomp imports
r2 -q -c 'iij' binary | jq '.[].name' | grep -Ei 'ptrace|prctl|seccomp'

# Common anti-analysis indicators:
# - ptrace(PTRACE_TRACEME) - Prevent debugger attach
# - prctl(PR_SET_DUMPABLE, 0) - Prevent core dumps
# - seccomp - Syscall filtering
# - /proc/self/status checks - Detect TracerPid

Runtime Detection

# If native execution possible:
strace -f ./binary 2>&1 | grep -E 'ptrace|prctl|seccomp|/proc/self'

Mitigation Strategies

Pattern Detection Bypass
ptrace(TRACEME) Returns EPERM if debugger attached Patch call to NOP, use QEMU
/proc/self/status check Reads TracerPid field Use QEMU (no /proc emulation)
Timing checks gettimeofday/rdtsc loops Single-step with GDB, patch checks
Self-checksum Reads own binary/memory Compute expected checksum, patch

When anti-analysis detected: Prefer QEMU-strace over GDB (fewer detection vectors), or patch checks in r2 before execution.


Error Recovery

Error Cause Solution
Unsupported syscall QEMU limitation Try Qiling or on-device
Invalid ELF image Wrong arch/sysroot Verify file output
Segfault at 0x0 Missing library Check ldd equivalent
QEMU hangs Blocking on I/O Add timeout, check strace
Anti-debugging Detection code Use Frida stalker mode
exec format error in Docker binfmt not registered Run tonistiigi/binfmt --install arm
ld-linux.so.3 not found Linker path mismatch Create symlink in container
libXXX.so not found Missing dependency apt install in container
Empty mount in Docker Colima /tmp issue Use ~/ path instead of /tmp/
ptrace: Operation not permitted strace in QEMU Use LD_DEBUG instead

Output Format

Record observations as structured data:

{
  "experiment": {
    "id": "exp_001",
    "method": "qemu_strace",
    "command": "qemu-arm -L /usr/arm-linux-gnueabihf -strace ./binary",
    "duration_secs": 12,
    "exit_code": 0
  },
  "syscall_summary": {
    "network": {
      "socket": 2,
      "connect": 1,
      "send": 5,
      "recv": 3
    },
    "file": {
      "openat": 4,
      "read": 12,
      "close": 4
    }
  },
  "network_connections": [
    {
      "family": "AF_INET",
      "address": "192.168.1.100",
      "port": 8443,
      "protocol": "tcp"
    }
  ],
  "files_accessed": [
    {"path": "/etc/config.json", "mode": "read"},
    {"path": "/var/log/app.log", "mode": "write"}
  ],
  "hypotheses_tested": [
    {
      "hypothesis_id": "hyp_001",
      "result": "confirmed",
      "evidence": "connect() to 192.168.1.100:8443 observed"
    }
  ]
}

Knowledge Journaling

After dynamic analysis, record findings for episodic memory:

[BINARY-RE:dynamic] {filename} (sha256: {hash})

Execution method: {qemu-strace|qemu-gdb|frida|on-device}
DECISION: Approved execution with {sandbox_config} (rationale: {why_safe})

Runtime observations:
  FACT: Binary reads {path} (source: strace openat)
  FACT: Binary connects to {ip}:{port} (source: strace connect)
  FACT: Binary writes to {path} (source: strace write)
  FACT: Function {addr} receives args {values} at runtime (source: gdb)

Syscall summary:
  Network: {socket|connect|send|recv counts}
  File: {open|read|write|close counts}
  Process: {fork|exec|clone counts}

HYPOTHESIS UPDATE: {confirmed or refined theory} (confidence: {new_value})
  Confirmed by: {runtime observation}
  Contradicted by: {if any}

New questions:
  QUESTION: {runtime-discovered unknown}

Answered questions:
  RESOLVED: {question} → {runtime evidence}

Example Journal Entry

[BINARY-RE:dynamic] thermostat_daemon (sha256: a1b2c3d4...)

Execution method: qemu-strace
DECISION: Approved execution with network-blocked sandbox (rationale: static analysis shows outbound only, no server)

Runtime observations:
  FACT: Binary reads /etc/thermostat.conf at startup (source: strace openat)
  FACT: Binary attempts connect to 93.184.216.34:443 (source: strace connect)
  FACT: Binary writes to /var/log/thermostat.log (source: strace openat O_WRONLY)
  FACT: sleep(30) called between network attempts (source: strace nanosleep)

Syscall summary:
  Network: socket(2), connect(1-blocked), send(0), recv(0)
  File: openat(4), read(12), write(8), close(4)
  Process: none

HYPOTHESIS UPDATE: Telemetry client confirmed - reads config, attempts HTTPS to thermco servers every 30s (confidence: 0.95)
  Confirmed by: connect() to expected IP, sleep(30) timing, config file read
  Contradicted by: none

Answered questions:
  RESOLVED: "Does it actually phone home?" → Yes, connect() to 93.184.216.34:443 observed
  RESOLVED: "What files does it access?" → /etc/thermostat.conf (read), /var/log/thermostat.log (write)

Next Steps

binary-re-synthesis to compile findings into report → Additional static analysis if new functions identified → Repeat with different inputs if behavior varies