Workflow reverse engineering perangkat USB di Linux berguna ketika tim perlu mengotomasi perangkat yang hanya punya aplikasi vendor, API tidak terdokumentasi, atau perilaku protokolnya perlu dipahami untuk kebutuhan internal seperti QA, provisioning, atau diagnosa. Pendekatan yang aman bukan dimulai dari menulis command, melainkan dari observasi pasif, pencatatan trafik, pemetaan state perangkat, lalu implementasi tool kecil yang read-only by default.

Artikel ini merangkum proses teknis yang bisa diterapkan tim: menangkap trafik USB, membaca interaksi aplikasi vendor, mengelompokkan pola command, membangun CLI minimal, memvalidasi hasilnya, menambahkan logging yang bisa diaudit, dan mengotomasi regression check. Fokusnya adalah alat Linux seperti usbmon, Wireshark, udev, strace, dan skrip pengujian, dengan guardrail agar eksperimen tidak merusak perangkat atau workstation utama.

Kenapa workflow ini relevan di tim engineering

Pendekatan ini berguna ketika:

  • Perangkat USB atau audio hanya punya GUI vendor, tetapi tim butuh otomasi untuk lab, factory test, atau CI hardware.
  • Dokumentasi protokol tidak tersedia atau tidak lengkap.
  • Tim perlu memverifikasi perubahan firmware, driver, atau alur setup perangkat secara berulang.
  • Ada kebutuhan observability: apa yang sebenarnya dikirim aplikasi vendor ke perangkat.

Namun, reverse engineering untuk perangkat fisik selalu punya risiko operasional. Karena itu, perlakukan proses ini sebagai pekerjaan engineering yang disiplin, bukan eksperimen ad-hoc di laptop utama.

Guardrail sebelum mulai: legalitas, keamanan, dan isolasi

Sebelum menangkap trafik atau mengirim command, tetapkan batasan kerja yang jelas.

1. Pastikan legalitas dan kebijakan internal

  • Periksa lisensi software vendor, syarat penggunaan perangkat, dan kebijakan legal internal.
  • Pastikan tujuan penggunaan adalah interoperabilitas, otomasi internal, atau diagnostik yang diizinkan.
  • Hindari mendistribusikan artefak yang mungkin melanggar hak cipta, seperti firmware atau binary vendor.

2. Asumsikan selalu ada risiko brick

Perangkat USB, termasuk perangkat audio, sering memiliki command yang mengubah konfigurasi persisten, masuk ke mode bootloader, atau menulis ke memori internal. Jika salah, perangkat bisa masuk state rusak atau sulit dipulihkan.

Prinsip aman: mulai dari operasi read-only, dokumentasikan state awal, dan jangan kirim command tulis sebelum Anda benar-benar paham efeknya.

3. Backup state perangkat

Jika perangkat mendukung pembacaan konfigurasi, simpan snapshot awal. Jika tidak, minimal catat:

  • VID/PID dan serial number.
  • Versi firmware bila tersedia.
  • Topologi USB saat terhubung.
  • Output descriptor dan endpoint.
  • Urutan aksi operator yang menghasilkan state tertentu.

4. Pisahkan eksperimen dari mesin kerja utama

  • Gunakan mesin lab khusus, VM dengan USB pass-through jika memadai, atau host Linux terpisah.
  • Matikan otomasi desktop yang bisa mengganggu akses ke perangkat.
  • Jangan campur alat reverse engineering dengan workstation yang dipakai kerja harian.

Gambaran workflow reverse engineering perangkat USB

Workflow yang praktis biasanya mengikuti urutan berikut:

  1. Identifikasi perangkat: lihat descriptor, endpoint, dan driver yang terpasang.
  2. Observasi pasif: tangkap trafik saat aplikasi vendor melakukan operasi normal.
  3. Korelasi perilaku: cocokkan aksi pengguna dengan transfer USB yang muncul.
  4. Kelompokkan command: bedakan command baca, tulis, inisialisasi, keepalive, dan error handling.
  5. Buat model protokol minimal: framing, direction, panjang payload, checksum bila ada.
  6. Implementasikan CLI kecil: mulai dari query status yang aman.
  7. Validasi hasil: bandingkan dengan aplikasi vendor dan cek idempotensi.
  8. Automasi regression check: agar perubahan parser atau encoder tidak merusak perilaku lama.

Langkah 1: identifikasi perangkat dan permukaan serangannya

Lihat descriptor dan driver yang aktif

Mulai dengan enumerasi dasar:

lsusb
lsusb -t
udevadm info --query=all --name=/dev/bus/usb/001/002

Dari sini Anda ingin tahu:

  • Vendor ID dan Product ID.
  • Apakah perangkat memakai interface standar seperti HID, audio, MIDI, atau vendor-specific.
  • Endpoint mana yang bulk, interrupt, atau control.
  • Driver kernel apa yang menempel.

Kalau perangkat audio mengikuti USB Audio class standar, sebagian fitur bisa diakses lewat interface generik. Tetapi pengaturan lanjutan sering tetap memakai vendor-specific control transfer atau endpoint tambahan. Di titik ini, jangan berasumsi semua fungsi perlu direverse. Pisahkan mana yang sudah standar dan mana yang benar-benar proprietary.

Gunakan udev untuk identitas yang stabil

Saat nanti membuat tool internal, jangan mengandalkan path bus USB yang berubah-ubah. Buat aturan udev agar perangkat dikenali secara konsisten.

SUBSYSTEM=="usb", ATTR{idVendor}=="1234", ATTR{idProduct}=="5678", TAG+="uaccess"

Untuk perangkat yang mengekspose node karakter atau HID raw, Anda bisa menambahkan symlink bernama tetap jika memang diperlukan. Tujuannya bukan kenyamanan semata, tetapi agar skrip pengujian dan logging merujuk ke identitas perangkat yang stabil.

Langkah 2: observasi trafik dengan usbmon dan Wireshark

Kapan memakai usbmon

usbmon adalah sumber data utama di Linux untuk mengamati trafik USB dari sisi host. Ia cocok untuk melihat transfer aktual tanpa harus memodifikasi aplikasi vendor.

Secara umum alurnya:

  1. Aktifkan atau pastikan usbmon tersedia.
  2. Hubungkan perangkat.
  3. Mulai capture pada bus yang benar.
  4. Jalankan aplikasi vendor dan lakukan satu aksi spesifik.
  5. Hentikan capture dan analisis hanya segmen waktu yang relevan.

Pisahkan aksi satu per satu. Misalnya:

  • Buka aplikasi.
  • Baca status perangkat.
  • Ubah satu parameter.
  • Kembalikan ke nilai awal.

Jangan merekam sesi panjang dengan banyak interaksi acak. Semakin bersih eksperimen, semakin mudah mengaitkan paket dengan tindakan.

Kapan memakai Wireshark

Wireshark memudahkan eksplorasi visual: filter endpoint, melihat urutan transfer, dan membandingkan payload antaraksi. Ini sangat membantu untuk menemukan pola seperti:

  • Header tetap pada setiap command.
  • Field panjang payload.
  • Counter, sequence number, atau checksum.
  • Pasangan request-response.
  • Polling periodik atau keepalive.

Jika Anda melihat banyak transfer berulang, kemungkinan itu hanya polling status atau sinkronisasi UI. Jangan langsung menganggap semua paket penting. Fokuslah pada delta saat satu aksi pengguna dijalankan.

Tips capture yang lebih berguna

  • Lakukan satu perubahan parameter per sesi.
  • Catat timestamp dan deskripsi aksi operator.
  • Gunakan nama file capture yang eksplisit, misalnya 2026-02-20-read-status.pcapng.
  • Simpan juga metadata eksperimen: firmware, host, kernel, dan aplikasi vendor yang dipakai.

Langkah 3: korelasikan trafik dengan proses user-space memakai strace

Capture USB menunjukkan apa yang dikirim ke perangkat. Tetapi kadang Anda juga perlu tahu bagaimana aplikasi vendor membukanya: file device mana yang dipakai, apakah lewat hidraw, libusb, ALSA control, atau node lain.

Di sinilah strace berguna.

strace -f -o trace.log /path/ke/aplikasi-vendor

Hal yang biasanya dicari:

  • Panggilan open ke /dev/hidraw*, /dev/bus/usb/*, atau node ALSA.
  • ioctl yang memberi petunjuk tipe interface.
  • read dan write dengan ukuran buffer tertentu.
  • Library yang diload, misalnya petunjuk bahwa aplikasi memakai backend USB tertentu.

strace tidak menggantikan capture USB, tetapi membantu mempersempit area investigasi. Misalnya, kalau aplikasi ternyata hanya berbicara ke hidraw, Anda bisa menguji replay lebih aman di level itu tanpa langsung menyentuh jalur lain.

Langkah 4: identifikasi protokol dan buat katalog command

Bedakan jenis transfer

Dalam banyak kasus, Anda akan menemukan campuran transfer berikut:

  • Control transfer: sering dipakai untuk setup, descriptor, atau vendor request kecil.
  • Bulk transfer: umum untuk payload yang lebih besar dan andal.
  • Interrupt transfer: sering dipakai HID atau notifikasi status periodik.

Tujuan Anda bukan mendekode semuanya sekaligus, tetapi membangun model minimum yang cukup untuk use case internal.

Buat tabel observasi command

Dokumentasi terbaik pada tahap awal adalah tabel sederhana yang bisa direview tim.

| Nama sementara   | Arah   | Endpoint | Panjang | Pemicu UI         | Efek dugaan        |
|------------------|--------|----------|---------|-------------------|--------------------|
| init_01          | host→dev | 0x01   | 64      | aplikasi dibuka   | handshake awal     |
| read_status      | host→dev | 0x01   | 16      | refresh status    | minta status       |
| status_reply     | dev→host | 0x81   | 64      | setelah read      | payload status     |
| set_param_x      | host→dev | 0x01   | 20      | ubah gain         | tulis parameter X  |

Tabel ini membantu memisahkan fakta dari asumsi. Kolom seperti Efek dugaan harus diperlakukan sebagai hipotesis sampai tervalidasi.

Cari pola framing

Perhatikan apakah payload memiliki struktur seperti:

  • Magic byte atau signature.
  • ID command.
  • Panjang payload.
  • Field channel, bank, atau parameter index.
  • Checksum atau CRC.

Kalau Anda mengubah satu parameter dari nilai A ke B dan hanya satu byte ikut berubah, itu petunjuk kuat tentang representasi data. Ulangi dengan beberapa nilai lain untuk memastikan field tersebut benar-benar nilai parameter, bukan sequence number atau checksum.

Waspadai false positive

Kesalahan umum adalah menyimpulkan fungsi command dari satu capture. Contoh: paket yang muncul setelah perubahan UI belum tentu command tulis; bisa jadi itu cuma query status lanjutan. Verifikasi dengan eksperimen terkontrol: jalankan aksi yang sama beberapa kali, dan bandingkan paket yang konsisten muncul sebelum dan sesudah perubahan state.

Langkah 5: implementasi CLI kecil yang aman dipakai developer

Begitu satu atau dua command read-only dipahami, buat tool internal yang sangat kecil. Tujuan fase ini adalah membuktikan pemahaman protokol, bukan membangun SDK lengkap.

Prinsip desain CLI

  • Read-only sebagai default.
  • Explicit write: command tulis harus butuh flag sadar-risiko seperti --write atau --yes-i-know.
  • Dry-run: tampilkan payload yang akan dikirim tanpa benar-benar mengirim.
  • Structured logging: simpan request, response, timestamp, dan identitas perangkat.
  • Timeout jelas: jangan menggantung tanpa batas.

Contoh struktur repo yang cukup realistis:

usb-tool/
├── README.md
├── docs/
│   ├── protocol-notes.md
│   ├── safety.md
│   └── captures/
├── captures/
│   ├── baseline/
│   └── annotated/
├── src/
│   ├── cli.py
│   ├── transport.py
│   ├── protocol.py
│   ├── commands.py
│   └── logging_utils.py
├── tests/
│   ├── test_protocol.py
│   ├── test_parser_fixtures.py
│   └── fixtures/
├── scripts/
│   ├── capture.sh
│   ├── smoke-read.sh
│   └── regression-check.sh
└── .github/workflows/
    └── ci.yml

Contoh arsitektur internal

Pisahkan tiga lapisan berikut:

  • Transport: detail akses ke hidraw, libusb, atau backend lain.
  • Protocol: encode/decode frame, validasi panjang, checksum, dan parser response.
  • Command layer: operasi domain seperti read_status atau set_monitor_mix.

Pemisahan ini penting karena hasil reverse engineering hampir selalu berubah. Jika parser atau framing direvisi, Anda tidak ingin seluruh CLI ikut berantakan.

Contoh kode CLI minimal

import argparse
import json
import logging

from transport import DeviceTransport
from commands import read_status

logging.basicConfig(level=logging.INFO)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--device", required=True, help="path device atau identitas udev")
    parser.add_argument("command", choices=["read-status"])
    parser.add_argument("--json", action="store_true")
    args = parser.parse_args()

    with DeviceTransport.open(args.device, read_only=True) as dev:
        if args.command == "read-status":
            status = read_status(dev)
            if args.json:
                print(json.dumps(status, indent=2, sort_keys=True))
            else:
                for k, v in status.items():
                    print(f"{k}: {v}")


if __name__ == "__main__":
    main()

Contoh di atas sengaja sederhana. Hal pentingnya adalah read_only=True, pemisahan command, dan output terstruktur yang mudah dipakai skrip lain.

Contoh parser frame yang defensif

def parse_status_frame(data: bytes) -> dict:
    if len(data) < 8:
        raise ValueError("frame terlalu pendek")

    if data[0] != 0xA5:
        raise ValueError("magic byte tidak cocok")

    payload_len = data[2]
    expected = 4 + payload_len
    if len(data) < expected:
        raise ValueError("panjang frame tidak lengkap")

    payload = data[3:3 + payload_len]
    return {
        "raw_hex": data.hex(),
        "payload_hex": payload.hex(),
        "status_code": payload[0] if payload else None,
    }

Jangan menulis parser yang permisif pada fase awal. Lebih baik gagal keras saat bentuk frame tidak sesuai daripada diam-diam salah menafsirkan state perangkat.

Langkah 6: validasi hasil reverse engineering

Setelah CLI bisa membaca status atau menjalankan satu command aman, validasi dengan beberapa lapisan.

Bandingkan dengan aplikasi vendor

  • Baca state dari aplikasi vendor.
  • Tutup atau diamkan aplikasi agar tidak berebut akses.
  • Baca state yang sama dengan CLI Anda.
  • Pastikan hasil konsisten pada beberapa siklus koneksi ulang.

Jika hasil berbeda, jangan langsung menyalahkan parser. Bisa jadi ada command inisialisasi yang terlewat, cache state di sisi aplikasi, atau polling yang mengubah konteks perangkat.

Uji idempotensi untuk operasi aman

Untuk command baca, ulangi berkali-kali dan cek bahwa:

  • Tidak ada perubahan state persisten.
  • Response tetap stabil pada kondisi input yang sama.
  • Tool tidak memicu reset, reconnect, atau timeout aneh.

Simpan fixture dari capture nyata

Fixtur payload nyata sangat membantu agar parser tidak rusak ketika kode direfaktor. Simpan frame mentah yang sudah dianotasi, lalu uji parser terhadap fixture tersebut.

def test_parse_status_fixture():
    raw = bytes.fromhex("a50104ff10203000")
    parsed = parse_status_frame(raw)
    assert parsed["status_code"] == 0xFF

Dengan cara ini, regression check bisa berjalan walaupun perangkat fisik tidak tersedia di CI.

Logging, audit trail, dan observability tool internal

Tool reverse engineering yang aman untuk developer harus meninggalkan jejak yang bisa diaudit. Logging bukan fitur tambahan, melainkan kontrol risiko.

Apa yang perlu dicatat

  • Timestamp UTC.
  • Identitas perangkat: VID/PID, serial jika ada.
  • Mode eksekusi: read-only, dry-run, write-enabled.
  • Command logis yang dijalankan.
  • Payload request dan response dalam bentuk hex.
  • Durasi, timeout, dan error.

Format log yang praktis

Gunakan log terstruktur, misalnya JSON line, agar mudah diproses otomatis. Hindari hanya mencetak teks bebas ke stdout jika tool ini akan dipakai lintas tim.

{"ts":"2026-02-20T10:15:00Z","device":"1234:5678","mode":"read-only","command":"read-status","request":"a50100","response":"a50104ff10203000"}

Jika ada data sensitif atau identifier unik, terapkan redaksi sesuai kebijakan internal.

Automasi regression check dan CI sederhana

Untuk tool internal, target awal CI bukan menguji hardware penuh, melainkan memastikan parser, encoder, dan CLI tidak rusak saat direfaktor.

Jenis pengujian yang masuk akal

  • Unit test: encode/decode frame, validasi checksum, parser response.
  • Fixture test: replay payload dari capture nyata.
  • CLI smoke test: validasi argumen, mode dry-run, format output JSON.
  • Static check: lint dan formatting.

Contoh skrip regression check lokal

#!/usr/bin/env bash
set -euo pipefail

python -m pytest -q
python -m src.cli --help > /dev/null
python -m src.cli --device dummy read-status --json || true

Pada contoh di atas, akses hardware sungguhan tidak diasumsikan tersedia. Untuk pengujian perangkat fisik, lebih aman jalankan sebagai job terpisah di lab runner yang memang terhubung ke hardware.

Contoh alur CI sederhana

name: ci

on:
  push:
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.x'
      - run: pip install -r requirements.txt
      - run: pip install -r requirements-dev.txt
      - run: ruff check src tests
      - run: python -m pytest -q

Jika tim memiliki lab hardware, tambahkan pipeline terpisah untuk manual approval atau jadwal malam hari. Jangan jalankan command write ke perangkat fisik pada setiap pull request tanpa kontrol ketat.

Skrip pengujian untuk perangkat nyata

Saat Anda mulai menguji pada hardware sesungguhnya, buat skrip yang eksplisit dan konservatif.

#!/usr/bin/env bash
set -euo pipefail

DEVICE="${1:?device wajib diisi}"
OUTDIR="logs/$(date -u +%Y%m%dT%H%M%SZ)"
mkdir -p "$OUTDIR"

python -m src.cli --device "$DEVICE" read-status --json | tee "$OUTDIR/status-before.json"
sleep 1
python -m src.cli --device "$DEVICE" read-status --json | tee "$OUTDIR/status-after.json"
diff -u "$OUTDIR/status-before.json" "$OUTDIR/status-after.json"

Skrip ini tidak melakukan write apa pun. Untuk fase awal, regression nyata yang paling bernilai justru memastikan operasi read-only tetap stabil dan tidak mengubah state perangkat.

Kesalahan umum dalam reverse engineering perangkat USB

  • Langsung mencoba write command sebelum memahami handshake dan state machine.
  • Mencampur banyak aksi dalam satu capture sehingga korelasi paket menjadi kabur.
  • Tidak mencatat firmware dan kondisi awal, padahal perbedaan kecil bisa mengubah hasil.
  • Mengabaikan command inisialisasi lalu bingung kenapa replay paket tunggal gagal.
  • Menganggap semua payload penting, padahal banyak perangkat punya polling status periodik.
  • Parser terlalu longgar sehingga bug tersembunyi sampai dipakai orang lain.
  • Menguji di workstation utama dan membiarkan aplikasi vendor berebut akses dengan tool internal.

Kapan pendekatan ini layak dipakai, dan kapan tidak

Layak dipakai ketika

  • Tim perlu otomasi internal yang berulang dan bernilai bisnis nyata.
  • Perangkat digunakan di lab atau proses operasional yang terkontrol.
  • Use case cukup sempit, misalnya baca status, verifikasi setup, atau provisioning terbatas.
  • Tim siap mendokumentasikan protokol, test fixture, dan guardrail operasional.

Kurang cocok ketika

  • Vendor sudah menyediakan API resmi yang memadai.
  • Perubahan firmware perangkat terlalu sering dan tidak bisa dipantau.
  • Risiko kerusakan perangkat lebih mahal daripada manfaat otomasi.
  • Tool akan dipakai luas tanpa tim pemilik yang siap merawatnya.

Penutup

Workflow reverse engineering perangkat USB yang berguna untuk tim bukan soal “membuka” protokol secepat mungkin, melainkan membangun proses yang dapat diulang, aman, dan bisa diuji. Mulailah dari observasi pasif dengan usbmon dan Wireshark, gunakan strace untuk memahami jalur akses user-space, dokumentasikan command sebagai hipotesis yang tervalidasi, lalu bangun CLI kecil dengan mode read-only, logging terstruktur, dan regression check berbasis fixture.

Jika dilakukan dengan guardrail yang tepat, pendekatan ini sangat efektif untuk perangkat USB atau audio yang perlu diotomasi di lingkungan engineering. Jika dilakukan tanpa disiplin, risikonya adalah interpretasi protokol yang salah, tool rapuh, atau bahkan perangkat yang masuk state rusak. Karena itu, utamakan keselamatan perangkat, auditability, dan reproducibility di setiap langkah.