profile

Hi! I'm 0x2a(wcampbell0x2a); Rust and C Software Engineer / Reverse Engineer. $ cat intro I'm a computer enthusiast who enjoys writing, reversing, and designing low-level systems software and infrastructure. You can find me at the following places. $ ls places -rw-r--r-- 1 wcampbell wcampbell github -rw-r--r-- 1 wcampbell wcampbell mastodon -rw-r--r-- 1 wcampbell wcampbell crates.io -rw-r--r-- 1 wcampbell wcampbell twitter $ tree -L 2 --noreport . ├── Projects │ ├── Deku │ │ ├── backhand │ │ ├── income │ │ ├── librarium │ │ ├── asterix-rs │ │ ├── ccsds-spacepacket │ │ ├── adsb_deku │ │ └── bintex │ ├── Rsadsb │ │ ├── adsb_deku │ │ ├── spotter │ │ ├── dump1090_rs │ │ ├── rsadsb-embedded │ │ └── FutureSDR │ └── Other │ ├── heretek │ ├── zerus │ ├── outsider │ ├── test-assets-ureq │ ├── kokiri │ ├── aftermath │ ├── statusbar │ ├── assert_hex │ ├── dbg_hex │ ├── privacy-log │ ├── no-std-io2 │ ├── compact-calendar-cli │ └── ratatui-style-ayu ├── Unpublished/research ├── Contributed ├── Ctfs └── Github Member organizations

# Projects

## Deku

I co-maintain the deku project, which provides Rust Programming Lanuage declarative binary reading and writing: bit-level, symmetric, serialization/deserialization. This has nerd-sniped me into writing a bunch of libraries at work and in the public-domain using this library.

$ cargo add deku
use deku::prelude::*;

#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
#[deku(endian = "big")]
struct DekuTest {
    #[deku(bits = 4)]
    field_a: u8,
    #[deku(bits = 4)]
    field_b: u8,
    field_c: u16,
}

fn main() {
    let data: Vec<u8> = vec![0b0110_1001, 0xBE, 0xEF];
    let (_rest, mut val) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap();
    assert_eq!(DekuTest {
        field_a: 0b0110,
        field_b: 0b1001,
        field_c: 0xBEEF,
    }, val);

    val.field_c = 0xC0FE;

    let data_out = val.to_bytes().unwrap();
    assert_eq!(vec![0b0110_1001, 0xC0, 0xFE], data_out);
}

### backhand

Library and binaries for the reading, creating, and modification of SquashFS file systems

$ cargo add backhand
$ cargo install backhand-cli
// read
let file = BufReader::new(File::open("file.squashfs").unwrap());
let read_filesystem = FilesystemReader::from_reader(file).unwrap();

// convert to writer
let mut write_filesystem = FilesystemWriter::from_fs_reader(&read_filesystem).unwrap();

// add file with data from slice
let d = NodeHeader::default();
let bytes = Cursor::new(b"Fear is the mind-killer.");
write_filesystem.push_file(bytes, "a/d/e/new_file", d);

// add file with data from file
let new_file = File::open("dune").unwrap();
write_filesystem.push_file(new_file, "/root/dune", d);

// replace a existing file
let bytes = Cursor::new(b"The sleeper must awaken.\n");
write_filesystem
    .replace_file("/a/b/c/d/e/first_file", bytes)
    .unwrap();

// write into a new file
let mut output = File::create("modified.squashfs").unwrap();
write_filesystem.write(&mut output).unwrap();
$ unsquashfs-backhand -i backhand-test/test-assets/test_04/out.squashfs
   Detected kind le_v4_0
      Read image
       Extracted squashfs-root/what/04
         Created squashfs-root/what/yikes
       Extracted squashfs-root/03
       Extracted squashfs-root/what/yikes/01
       Extracted squashfs-root/what/yikes/02
         Created squashfs-root/woah
       Extracted squashfs-root/woah/05
        Finished extraction of 9 nodes in 0 seconds

### income

Library and binaries for the reading of UBI images

$ cargo add income
$ income [IMAGE_PATH]

### librarium

Library and binaries for the reading, creating, and modification of cpio archives

$ cargo add librarium
$ cargo install librarium-cli

#### Read

use librarium::{ArchiveReader, NewcHeader};

let mut file = File::open("archive.cpio")?;
let mut archive = ArchiveReader::<NewcHeader>::from_reader_with_offset(&mut file, 0)?;
for object in &archive.objects.inner {
    archive.reader.extract_data(object, &mut out)?;
}

#### Write

let file = File::create("archive.cpio").unwrap();
let mut writer = ArchiveWriter::<NewcHeader>::new(Box::new(file));

// A
let a_data = "a\n".as_bytes();
let a_header = Header { name: "a".to_string(), ..Header::default()};
writer.push_file(Cursor::new(a_data), a_header).unwrap();

// write to archive
writer.write().unwrap();

### asterix-rs

Library for the parsing and generating of ASTERIX packets

$ cargo add asterix
use asterix::AsterixPacket;

let bytes = &[0x22, 0x00, 0x0b, 0xf0, 0x19, 0x0d, 0x02, 0x35, 0x6d, 0xfa, 0x60];
let (_, packet) = AsterixPacket::from_bytes((bytes, 0))?;

### KubOS-Preservation-Group/ccsds-spacepacket

Implementation of the CCSDS Space Packet Primary Header in Rust

$ cargo add ccsds-spacepacket
use ccsds_spacepacket::PrimaryHeader;

let raw = b"\x00\x00\xc0\x00\x00\x40\xff\xff";
let (rest, parsed) = PrimaryHeader::from_bytes((raw, 0))?;

### adsb_deku

See below

$ cargo add adsb_deku
use hexlit::hex;
use adsb_deku::Frame;

let bytes = hex!("8da2c1bd587ba2adb31799cb802b");
let frame = Frame::from_bytes(&bytes).unwrap();
assert_eq!(
        r#" Extended Squitter Airborne position (barometric altitude)
  Address:       a2c1bd (Mode S / ADS-B)
  Air/Ground:    airborne
  Altitude:      23650 ft barometric
  CPR type:      Airborne
  CPR odd flag:  even
  CPR latitude:  (87769)
  CPR longitude: (71577)
"#,
    frame.to_string()
);

### bintex

Create bytefield latex digrams with the use of rust proc-macros and deku

$ cargo add bintex
use bintex::BinTex;

#[derive(BinTex)]
#[bintex(bit_width = 32)]
struct Ipv6 {
    #[deku(bits = "4")]
    version: u8,
    length: u16,
}

#### unpublished/research only

  • xz-deku - Library for reading XZ compression headers
  • f12022-deku - Library for the parsing of PC f1 2022 UDP telemetry packets + tui
  • rusty-chips - CHIP-8 emulator

## Rsadsb

Rust software suite for ADS-B demodulation, decoding, and processing.

  • homepage - Announcements, Overview, Blog, and Quick Start guide. See quickstart for more details and installation steps.

### adsb_deku

Library and binaries for the parsing and generation of ADS-B packets and display of information

# Use as a library
$ cargo add adsb_deku

# Install TUI
$ cargo install --git https://github.com/rsadsb/adsb_deku rsadsb_apps --bin radar --locked

### spotter

Rust ADS-B web server providing current information in JSON

### dump1090_rs

Multi-SDR supported Rust translation of the popular dump1090 project for ADS-B demodulation

### rsadsb-embedded

Experimental applications using the no_std feature of rsadsb/adsb_deku

### FutureSDR

An Async SDR Runtime for Heterogeneous Architectures using my library

#### In The News

#### unpublished/research only

  • elons-jets-rs - Notify when one of Elon Musk's jets flyover your own ADS-B receiver

## Other

### heretek

GDB TUI Dashboard for the understanding of vast knowledge

  • No gdbserver requirements: Many vendors ship invalid `gdbserver` binaries, this works on remote targets with just `gdb`, `nc`, `cat`, and `mkfifo`.
  • No python requirements: Many vendors ship `gdb` without python support.
  • Architecture agnostic: `heretek` only uses information given by `gdb`, no extra code required!
$ cargo install heretek --locked

### zerus

Lightweight binary to download only project required crates for offline crates.io mirror

$ cargo install zerus --locked

$ zerus mirror ../deku/Cargo.toml --build-std nightly --skip-git-index
[-] Created mirror
[-] Vendoring: ../deku/Cargo.toml
[-] Vendoring: .rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/Cargo.toml
[-] Downloading: https://static.crates.io/crates/aho-corasick/aho-corasick-1.1.4.crate
[-] Downloading: https://static.crates.io/crates/hashbrown/hashbrown-0.16.1.crate
[-] Downloading: https://static.crates.io/crates/addr2line/addr2line-0.25.1.crate
[-] Downloading: https://static.crates.io/crates/rustc-demangle/rustc-demangle-0.1.26.crate
[-] Downloading: https://static.crates.io/crates/rustc-literal-escaper/rustc-literal-escaper-0.0.5.crate
[-] Downloading: https://static.crates.io/crates/adler2/adler2-2.0.1.crate
[-] Downloading: https://static.crates.io/crates/rustc-std-workspace-alloc/rustc-std-workspace-alloc-1.99.0.crate
[-] Downloading: https://static.crates.io/crates/hermit-abi/hermit-abi-0.5.2.crate
[SNIP]
[-] Downloading: https://static.crates.io/crates/web-sys/web-sys-0.3.82.crate
[-] Downloading: https://static.crates.io/crates/target-triple/target-triple-1.0.0.crate
[-] Downloading: https://static.crates.io/crates/serde_json/serde_json-1.0.145.crate
[-] Downloading: https://static.crates.io/crates/serde_spanned/serde_spanned-1.0.3.crate
[-] Downloading: https://static.crates.io/crates/slab/slab-0.4.11.crate
[-] Finished downloading crates

### outsider

Test artifact changes locally from multiple projects that already use gitlab-art

$ cargo install outsider --locked

The following projects depends on project: `kosma/foobar-firmware`, and we have changes locally that we want to test before pushing to the gitlab repo. We _could_ just `cp` them, but `outsider` removes that complexity and uses the `artifacts.yml` file.

- project: kosma/foobar-firmware
  ref: 1.4.0
  job: firmware-8051
  install:
    build/8051/release/firmware.bin: blobs/firmware-8051.blob

We have now updated the firmware, good thing we can easily push these changes to the other repo :)

# build build/8051/release/firmware.bin
(kosma/foobar-firmware) $ make

# move artifacts to the correct placement in project-a
(kosma/foobar-firmware) $ outsider ./project-a/artifacts.yml --project kosma/foobar-firmware

### test-assets-ureq

Download test assets with ureq, managing them outside of git

$ cargo add test-assets-ureq

Example toml of test assets to download.

[test_assets.test_00]
filepath = "out.squashfs"
hash = "976c1638d8c1ba8014de6c64b196cbd70a5acf031be10a8e7f649536193c8e78"
url = "https://wcampbell.dev/squashfs/testing/test_00/out.squashfs"

These may either be downloaded using native rust code, or the use of our binary.

let file_content = fs::read_to_string("test.toml").unwrap();
let parsed: TestAsset = toml::de::from_str(&file_content).unwrap();
let assets = parsed.values();
dl_test_files_backoff(&assets, "test-assets", true, Duration::from_secs(1)).unwrap();
Usage: dl [OPTIONS] <FILE> <PATH>

Arguments:
  <FILE>  Path to the TOML file to read
  <PATH>  Base path to write downloaded files

Options:
      --assets <ASSETS>  List of specific asset names to download (downloads all if not specified)
  -h, --help             Print help

### kokiri

Test revisions of crates again other revisions of crates

$ cargo install kokiri --locked

Test master of deku against other crates hosted on github.

[test]
url = "https://github.com/sharksforarms/deku"
name = "deku"
rev = "master"

[[instructions]]
# Required
url = "https://github.com/wcampbell0x2a/backhand.git"
# Required
name = "backhand"
# Optional
package = "backhand"
# Optional (master if omitted)
rev = "master"
# Optional cmd to take before test cmd
before_action = "cargo build --bins"

[[instructions]]
url = "https://github.com/wcampbell0x2a/librarium"
name = "librarium"
package = "librarium"
$ kokiri instructions.toml --root-dir tmp test
[-] Cloning into TempDir { path: "/home/wcampbell/projects/wcampbell/kokiri/tmp/.tmpklNQpn" }
Cloning into 'deku'...
remote: Enumerating objects: 5778, done.
remote: Counting objects: 100% (2280/2280), done.
remote: Compressing objects: 100% (616/616), done.
remote: Total 5778 (delta 2004), reused 1686 (delta 1664), pack-reused 3498 (from 3)
Receiving objects: 100% (5778/5778), 1.33 MiB | 5.05 MiB/s, done.
Resolving deltas: 100% (3686/3686), done.
[-] success!
[-] Cloning into "/home/wcampbell/projects/wcampbell/kokiri/tmp/.tmpUlB2Vg"
Cloning into 'backhand'...
remote: Enumerating objects: 7766, done.
remote: Counting objects: 100% (206/206), done.
remote: Compressing objects: 100% (111/111), done.
remote: Total 7766 (delta 118), reused 101 (delta 92), pack-reused 7560 (from 3)
Receiving objects: 100% (7766/7766), 2.09 MiB | 1.02 MiB/s, done.
Resolving deltas: 100% (5218/5218), done.
[-] success!
[-] running extra cmd: cargo build --bins

### aftermath

Find-and-replace, commit, check, and push new changes to CI files for multiple projects

$ cargo install aftermath-bin --locked

### statusbar

dwm statusbar, now in Rust!

$ cargo install statusbar --locked

Generates all the information a statusbar needs!

[sietch][wcampbell] -> cpu 14%, mem 07%, net [192.168.1.13], bat [100%, 100%], 2025-12-22 22:58:17

### assert_hex

Rust library to display assert panics in hexadecimal format

$ cargo add assert_hex
use assert_hex::assert_eq_hex;

let expected = vec![0x01, 0x02, 0x03];
let actual = vec![0x01, 0x02, 0x04];
assert_eq_hex!(expected, actual);

### dbg_hex

Display dbg result in hexadecimal {:#x?} format

$ cargo add dbg_hex
use dbg_hex::dbg_hex;

dbg_hex!(0x16 + 0x16);
// Output: [src/lib.rs:38] 0x16 + 0x16 = 0x2c

### privacy-log

rust-lang/log, but without file and line information

$ cargo add privacy-log
use privacy_log::{info, debug, error};

info!("Application started");
debug!("Debug message");
error!("Error message");

### no-std-io2

std::io for no_std, used in deku

$ cargo add no-std-io2
use no_std_io2::io::Write;

// Works with any type implementing Write trait
serial.write_all(b"hello")?;

### compact-calendar-cli

Compact year-at-a-glance calendar CLI with TOML-based event highlighting

$ cargo install compact-calendar-cli --locked

### ratatui-style-ayu

Ayu color theme for Ratatui applications

$ cargo add ratatui-style-ayu
use ratatui_style_ayu::ayu_dark;

// Use the color constants
let bg = ayu_dark::BACKGROUND;
let fg = ayu_dark::FOREGROUND;

## Unpublished/research

  • dotfiles - My linux dotfiles
  • sorensen - Cursed Compression Algorithm
  • cargo-decompile - [!] A cargo subcommand that displays ghidra function output through the use of the {rizin, radare2}-ghidra
  • freestanding - Small freestanding ARM binary calling function already in memory
  • karkinOS - Hobby OS and bootloader
  • saleae-rs - rust library for interacting with saleae devices
  • usb-notify - (C) USB device insert notifications using the linux udev,uevent and libnotify
  • mint-cli - (Python) Display account net worth and current monthly budget in your terminal. Uses the python-mintapi

## Contributed

and many others...

# Ctfs

# Github Member organizations

a proud member of the blue team of 512KB club