• Stars
    star
    284
  • Rank 145,616 (Top 3 %)
  • Language
    Rust
  • License
    Other
  • Created over 4 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Hiding messages in x86 programs using semantic duals

steg86

license CI

steg86 is a format-agnostic steganographic tool for x86 and AMD64 binaries. You can use it to hide information in compiled programs, regardless of executable format (PE, ELF, Mach-O, raw, &c). It has no performance or size impact on the files that it modifies (adding a message does not increase binary size or decrease execution speed).

For more details on how steg86 works, see the Theory of Operation section.

Installation

steg86 can be installed via cargo:

$ cargo install steg86

Alternatively, you can build it in this repository with cargo build:

$ cargo build

Usage

See steg86 --help for a full list of flags and subcommands.

Profiling

To profile a binary for steganographic suitability:

$ steg86 profile /bin/bash
Summary for /bin/bash:
  175828 total instructions
  27957 potential semantic pairs
  19 potential commutative instructions
  27944 bits of information capacity (3493 bytes, approx. 3KB)

Embedding

To embed a message into a binary:

$ steg86 embed /bin/bash ./bash.steg <<< "here is my secret message"

By default, steg86 embed writes its output to $input.steg. For example, /lib64/ld-linux-x86-64.so.2 would become /lib64/ld-linux-x86-64.so.2.steg.

steg86 embed will exit with a non-zero status if the message cannot be embedded (e.g., if it's too large).

Extraction

To extract a message from a binary:

$ steg86 extract bash.steg > my_message
$ cat message
here is my secret message

steg86 extract will exit with a non-zero status if a message cannot be extracted (e.g., if it can't find one).

Theory of Operation

steg86 takes advantage of one of x86's encoding peculiarities: the R/M field of the ModR/M byte:

  7  6  5  4  3  2  1  0
 -------------------------
 | MOD |  REG  |   R/M   |
 -------------------------

The ModR/M byte is normally used to support both register-to-memory and memory-to-register variants of the same instruction. For example, the MOV instruction has the following variants (among many others):

opcode mnemonic
89 /r MOV r/m32,r32
8B /r MOV r32,r/m32

Because the ModR/M field can encode either a memory addressing operation or a bare register, opcodes that support both register-to-memory and memory-to-register operations also support multiple encodings of register-to-register operations.

For example, mov eax, ebx can be encoded as either 89 d8 or 8b c3 without any semantic changes. This gives us one bit of information per duplicated instruction semantic. Given enough register-to-register instructions with multiple encodings, we can hide entire messages with those bits.

Additionally, because these semantically identical encodings are frequently the same size, we can modify preexisting binaries without having to fix relocations or RIP-relative addressing.

steg86 does primitive binary translation to accomplish these goals. It uses iced-x86 for encoding and decoding, and goblin for binary format wrangling.

Prior work

The inspiration for steg86 came from @inventednight, who described it as an adaptation of a similar idea (also theirs) for RISC-V binaries.

The technique mentioned above is discussed in detail in Hydan: Hiding Information in Program Binaries (2004).

steg86 constitutes a separate discovery of Hydan's technique and was written entirely independently; the refinements discussed in the paper may or may not be more optimal than the ones implemented in steg86.

Future improvements

  • steg86 currently limits the embedded message to 16KB. This is a purely artificial limitation that could be resolved with some small format changes.

  • x86 (and AMD64) both have multi-byte NOPs, for alignment purposes. Additional information can be hidden in these in a few ways:

    • The OF 1F /0 multi-byte NOP can be up to 9 bytes, of which up to 5 are free (SIB + 4-byte displacement).
    • There are longer NOPs (11, 15 bytes) that may also be usable.
  • Going beyond register-to-register duals and rewriting add/sub, as Hydan does.

More Repositories

1

ff2mpv

A Firefox/Chrome add-on for playing URLs in mpv.
PowerShell
506
star
2

kbs2

A secret manager backed by age
Rust
107
star
3

shaq

A CLI client for Shazam
Python
99
star
4

screenfetch-c

A rewrite of screenFetch in C.
C
71
star
5

mollusc

Pure-Rust libraries for parsing, interpreting, and analyzing LLVM
Rust
67
star
6

toml2json

A very small CLI for converting TOML to JSON
Rust
63
star
7

pyrage

Python bindings for rage (age in Rust)
Rust
45
star
8

bindef

A DSL and command-line tool for generating binary files.
Ruby
37
star
9

procmaps.py

Python bindings for procmaps.rs
Rust
35
star
10

snippets

Short (but useful) scripts and programs.
Ruby
32
star
11

yossarian-bot

An IRC bot with a bunch of features.
Ruby
30
star
12

qrencode.cr

Crystal bindings for libqrencode (qrencode), a library for QR code generation
Crystal
29
star
13

ordered_enum

Totally ordered enums for Python.
Python
26
star
14

llvm-passgen

A small tool for quickly generating LLVM passes
Rust
26
star
15

usb-ids.rs

Cross-platform Rust wrappers for the USB ID Repository
Rust
22
star
16

x_do.cr

Crystal bindings for libxdo (xdotool)
Crystal
18
star
17

upgrayedd

Ergonomic function interposition in Rust
Rust
16
star
18

ruby-mpv

A Ruby library for controlling mpv processes.
Ruby
15
star
19

notify.cr

A Crystal library for desktop notifications.
Crystal
14
star
20

dotfiles

Configuration files, with some information removed.
Shell
12
star
21

procmaps.rs

A small Rust library for reading process maps from procfs
Rust
12
star
22

skipjack.rs

A straight-line implementation of the Skipjack cipher in Rust
Rust
11
star
23

libbdiff

A library for creating and patching binary diffs. Based on bsdiff.
C
11
star
24

libmsr

A library for reading, writing and analysis of magnetic stripe information.
C
10
star
25

ruby-inih

A Ruby wrapper for inih (a simple C INI parser)
C
7
star
26

SimpleSession

A window-oriented session manager for Sublime Text.
Python
6
star
27

lzfse.rb

Ruby bindings for Apple's LZFSE, including LZVN
C
6
star
28

cazart

Flask + schema = cazart!
Python
6
star
29

pledger

A small personal expense ledger.
Rust
6
star
30

abi3info

Programmatic access to Python's limited API and abi3 information
Python
5
star
31

pgpkeydump

A tool for dumping PGP keys as JSON
Rust
5
star
32

nicer-bash

Things to make bash scripting nicer.
Shell
5
star
33

msr-utils

Utilities split off from libmsr.
C
4
star
34

ruby-eval-in

A Ruby interface to https://eval.in/
Ruby
4
star
35

et

ET - the extraterrestrial botnet
C
3
star
36

i3.cr

A Crystal interface to the i3 window manager.
Crystal
3
star
37

MediaKeys

Media keys on Windows, without actual media keys.
C
3
star
38

github-actions-models

Unofficial Rust data models for GitHub Actions
Rust
3
star
39

pypi-pgp-statistics

Scripts and data from analyzing PGP signatures uploaded to PyPI
Python
3
star
40

abbrev.cr

A straightforward port of Ruby's Abbrev to Crystal.
Crystal
3
star
41

baseperm

A small tool for generating valid permutations of strings in baseN alphabets.
Rust
3
star
42

nvis

A very simple input visualizer
Rust
2
star
43

documerica

Data and a Twitter bot for the EPA's DOCUMERICA (1972-1977) program.
Python
2
star
44

bupkis

A small static album generator
Rust
2
star
45

tum

[WIP] A tiny useless machine.
C
2
star
46

pgp-wordlist.cr

A Crystal library for generating PGP word lists.
Crystal
2
star
47

autopost

Auto-posts social media updates
Python
2
star
48

sunxdcc.rs

A small, unofficial Rust wrapper for the SunXDCC search engine
Rust
2
star
49

eman

Utilities for embedded manpages.
Shell
1
star
50

sxbiff

xbiff with signals
C
1
star
51

git-contrib

MIGRATED. Contributors file generator for git repositories.
Ruby
1
star
52

ruby-macho-utils

Command-line utilities for ruby-macho.
Ruby
1
star
53

rsus

A really simple upload service.
Crystal
1
star
54

website

An old git mirror of woodruffw.us. NO LONGER USED.
HTML
1
star
55

xnelson

Nelson, for X.
C
1
star
56

SimpleMail

A very simple Java program for sending (not receiving) emails via SMTP. Utilizes javax.mail.
Java
1
star
57

NIST-Beacon

A perl module for interacting with NIST's randomness beacon.
Perl
1
star
58

CGoL

Conway's Game of Life, in Java.
Java
1
star
59

ruby-upworthy

A Ruby gem for generating clickbait titles. Based on http://upworthygenerator.com.
Ruby
1
star
60

xroach

A maintained copy of `xroach`
C
1
star
61

SublimeLinter-contrib-git-lint-commit

A SublimeLinter plugin for linting Git commit messages with git-lint-commit
Python
1
star
62

netstring.cr

A library for parsing netstrings in Crystal
Crystal
1
star
63

tepm

A tiny executable package manager.
Shell
1
star
64

cbor.cr

Crystal bindings for libcbor
Crystal
1
star