Compiletime string literal obfuscation for Rust.

Overview

String Obfuscation

MIT License crates.io docs.rs Build status

Compiletime string constant obfuscation for Rust.

The string constant itself is embedded in obfuscated form and deobfuscated locally. This reference to a temporary value must be used in the same statement it was generated. See the documentation for more advanced use cases.

Examples

The obfstr! macro returns the deobfuscated string as a temporary value:

assert_eq!(obfstr::obfstr!("Hello 🌍"), "Hello 🌍");

The wide! macro provides compiletime utf16 string constants:

let expected = &['W' as u16, 'i' as u16, 'd' as u16, 'e' as u16, 0];
assert_eq!(obfstr::wide!("Wide\0"), expected);

The random! macro provides compiletime random values:

const RND: i32 = obfstr::random!(u8) as i32;
assert!(RND >= 0 && RND <= 255);

Compiletime random values are based on file!(), line!(), column!() and a fixed seed to ensure reproducibility. This fixed seed is stored as text in the environment variable OBFSTR_SEED and can be changed as desired.

License

Licensed under MIT License, see license.txt.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, shall be licensed as above, without any additional terms or conditions.

Comments
  • Don't enable RUST_BOOTSTRAP in build.rs

    Don't enable RUST_BOOTSTRAP in build.rs

    The crate is currently "usable" on stable rust, despite using nightly-only feature, by enabling RUST_BOOTSTRAP=1 in build.rs. This is a very bad idea. This flag is only meant to bootstrap the compiler itself, and any other use of it is unsupported and might lead to the code breaking if/when the API changes. This is not unheard of: Nightly features aren't finalized and often changes shape prior to stabilization.

    The currently used features are also not very stable, const_generics and const_fn can easily cause ICEs in the compiler or soundness issues in the final binary, due to implementation bugs.

    IMO, this crate shouldn't abuse RUST_BOOTSTRAP like this. The correct way is to tell the users to use a nightly compiler. If that's not possible, the use of RUST_BOOTSTRAP should at least be called out in the README so users can make an informed decision about using this crate.

    opened by roblabla 13
  • constant byte array obfuscation

    constant byte array obfuscation

    Would be useful if there was obfbytes!, which takes a byte array (whether it be b"\x2A\x2A", [42, 42] or include_bytes!("data.bin")), and encrypts+obfuscates it.

    My use case is making it more difficult to find a hardcoded public key used for validation.

    opened by Absolucy 8
  • IDA 7.5 can see through obfstr 0.2 obfuscation

    IDA 7.5 can see through obfstr 0.2 obfuscation

    When decompiling a binary obfuscating with obfstr 0.2 with IDA/Hexrays 7.5, the obfuscation is immediately undone, and the XREF immediately give away the string location. See below for the source code, and the decompiler and asm output. This was tested with rust 1.48.0.

    obfstr 0.1 does not suffer from this: The strings are properly obfuscated, and IDA fails to find any xrefs for it. I believe the difference comes from obfstr 0.1 having a random offset into the string, which confuses IDA, leaving its XREF analysis and automatic deobfuscators inoperable. Another issue is that the one time pad to deobfuscate the string is kept in .rodata (due to being passed as an array to the deobfuscate method) while obfstr 0.1 would only get passed the initial round key.

    I imagine the fix would go like this: Change the deobfuscate method to take a random offset like obfstr 0.1 in order to break the xrefs, and generate the XOR round keys at runtime instead of compile time.

    Source code:

    use obfstr::obfstr;
    fn main() {
        println!("aaaaaaaaaaaa");
        println!("{}", obfstr!("bbbbbbbbbbbb"));
        println!("{}", obfstr!("cccccccccccc"));
    }
    
    0.2 Hexrays decompiler view

    Image Pasted at 2021-1-6 14-51

    0.1 Hexrays Decompiler View

    Image Pasted at 2021-1-6 14-57

    0.2 Assembly view

    Image Pasted at 2021-1-6 14-51(1)

    0.2 Data X-Refs

    Image Pasted at 2021-1-6 14-52

    0.1 Data X-Refs

    Image Pasted at 2021-1-6 14-56

    opened by roblabla 4
  • Handle `Group`s with `Delimiter::None`

    Handle `Group`s with `Delimiter::None`

    Currently, rustc does not pass the exact original TokenStream to proc-macros in several cases. This has many undesirable effects, such as losing correct location information in error message. See https://github.com/rust-lang/rust/issues/43081 for more details

    In the future, rustc will begin passing the correct TokenStream to proc-macros. As a result, some tokens may be wrapped in a TokenTree::Group with Delimiter::None (when the tokens originally came from a macro_rules!) macro expansion.

    I've determined that this change will cause your crate to stop compiling. This PR updates obfstr to be compatible with both the old and new TokenStream contents.

    You can verify this PR by attempting to build your crate as follows:

    rustup toolchain install nightly-2020-05-29
    cargo +nightly-2020-05-29 build
    

    This will built your crate with an older nightly build that contains the change we want to eventually roll out. On this compiler version, your crate should fail to compile without this PR, and successfully compile with this PR.

    If you have any questions, feel free to ask me. See https://github.com/rust-lang/rust/issues/72622 for more details

    opened by Aaron1011 2
  • Edition 2021 breaks the L prefix for obfstr.

    Edition 2021 breaks the L prefix for obfstr.

    error: prefix `L` is unknown
       --> project/src/sys_windows.rs:183:38
        |
    183 |         obfstr!(L"test.dll\0")
        |                 ^ unknown prefix
        |
        = note: prefixed identifiers and literals are reserved since Rust 2021
    help: consider inserting whitespace here
        |
    183 -         obfstr!(L"test.dll\0")
    183 +         obfstr!(L "test.dll\0")
        |
    
    opened by roblabla 1
  • Code Cleanup

    Code Cleanup

    Includes breaking changes:

    • Remove obflocal, obfconst, obfeq, ObfString, ObfBuffer
    • Change hash to DJB2 to xor variation
    • Move xref to its own module
    • Remove static mut to just static hopefully the xref breaking keeps IDA at bay The problem with static mut is that it makes it hard to protect against malicious modification
    opened by CasualX 1
  • const String -> u32 ?

    const String -> u32 ?

    Heya, I came across your article at https://casualhacks.net/blog/2020-05-31/compiletime-processing/

    Was wondering if you've looked into doing this for creating compile-time hashes from strings?

    For example, I'd like to be able to do const U_POSITION:u32 = hash!("u_color"); and know that it's the same value as some other usage elsewhere. Speed and avoiding collisions are important, but it doesn't need to be cryptographically secure.

    opened by dakom 1
  • obfstr 0.1.x: Support raw strings

    obfstr 0.1.x: Support raw strings

    obfstr 1.x currently doesn't support raw string, e.g. the following causes a panic:

    obfstr!(r"do\stuff"); // Panics
    obfstr!(r#"do\stuff"#); // Panics too
    

    To fix this, obfstr-impl's string_parse should probably be updated to take a TokenStream instead of a Literal, and check each token in the stream.

    opened by roblabla 1
  • 0.1.x API without RUSTC_BOOTSTRAP

    0.1.x API without RUSTC_BOOTSTRAP

    Fixes #17 .

    This is my latest attempt at removing RUSTC_BOOTSTRAP from obfstr, while keeping compatibility with as much of the old API as possible. I believe this version to be maximally compatible.

    I think this will be ready for release. I would appreciate a second set of eyes to confirm that what I'm doing is actually safe though. In particular, that it is sound for decrypt and as_str to cast the generic parameter to a slice thanks to the constructor being unsafe.

    opened by roblabla 1
  • Add license file into the `impl` sub-crate

    Add license file into the `impl` sub-crate

    Sadly archive on crates.io for obfstr-impl does not contain. That is resolvable in 3 simple ways: use license-file, add a symlink in the subdirectory, copy file in the subdirectory. Not sure which one you prefer, so not sending a PR.

    opened by ignatenkobrain 1
  • Fix typo and simplify entropy

    Fix typo and simplify entropy

    Obfstr uses the original string as a source of entropy per invocation. A typo made it always use $ e instead of the original string.

    Introduce internal __entropy to avoid unnecessary const items.

    opened by CasualX 0
  • Break ghidra constant folding through inline-never fns

    Break ghidra constant folding through inline-never fns

    Heyo,

    I just updated my project to the obfstr 4, and overall the improvements are quite nice! However, there is one small downside compared to the previous version: Obfstr 4 generates a huge block of data that xrefs every code dealing with obfuscated string in the .data block:

    image

    This is not ideal, as it gives a reverser a simple way to find all the code offsets to obfuscated strings, making the creation of an automated deobfuscation tool a bit easier.

    Digging into the code, I figured that this change came from the new xref code. After reading over #44, I eventually figured that this was done to break Ghidra's constant folding which defeated much of the obfuscation.

    So I tried to take a different approach here: Instead of storing the xref offsets in the .data, I figured they could be stored in a dedicated function marked inline(never). In theory, ghidra will not be able to "see through" the call, and thus break the constant folding.

    Here's the result: image


    This approach has the other benefits of not using the .data segment, which should make code integrity checks properly verify that the xref offsets aren't tampered with.

    opened by roblabla 1
Owner
Casper
Casper
An esoteric language/compiler written with Rust and Rust LLVM bindings

MeidoLang (パむドラング) A not so useful and esoteric language. The goal of this project was to contain some quirky or novel syntax in a stack-style program

null 0 Dec 24, 2021
Rust-verification-tools - RVT is a collection of tools/libraries to support both static and dynamic verification of Rust programs.

Rust verification tools This is a collection of tools/libraries to support both static and dynamic verification of Rust programs. We see static verifi

null 253 Dec 31, 2022
Rust bindings for libinjection

libinjection-rs Rust bindings for libinjection. How to use Add libinjection to dependencies of Cargo.toml: libinjection = "0.2" Import crate: extern c

ArvanCloud 35 Sep 24, 2022
A simple password manager written in Rust

ripasso A simple password manager written in Rust. The root crate ripasso is a library for accessing and decrypting passwords stored in pass format (G

Joakim Lundborg 548 Dec 26, 2022
tcp connection hijacker, rust rewrite of shijack

rshijack tcp connection hijacker, rust rewrite of shijack from 2001. This was written for TAMUctf 2018, brick house 100. The target was a telnet serve

null 377 Jan 1, 2023
A fast, simple, recursive content discovery tool written in Rust.

A simple, fast, recursive content discovery tool written in Rust ?? Releases ✨ Example Usage ✨ Contributing ✨ Documentation ?? ?? What the heck is a f

epi 3.6k Dec 30, 2022
link is a command and control framework written in rust

link link is a command and control framework written in rust. Currently in alpha. Table of Contents Introduction Features Feedback Build Process Ackno

null 427 Dec 24, 2022
CVEs for the Rust standard library

Rust CVE Preface This is a list of CVEs for unsound APIs in the Rust standard library. These bugs break Rust's memory safety guarantee and lead to sec

Yechan Bae 26 Dec 4, 2022
Rust bindings for VirusTotal/Yara

yara-rust Bindings for the Yara library from VirusTotal. More documentation can be found on the Yara's documentation. Example The implementation is in

null 43 Dec 17, 2022
Rust library for building and running BPF/eBPF modules

RedBPF A Rust eBPF toolchain. Overview The redbpf project is a collection of tools and libraries to build eBPF programs using Rust. It includes: redbp

foniod 1.5k Jan 1, 2023
Rust library for developing safe canisters.

IC Kit This library provides an alternative to ic-cdk that can help developers write canisters and unit test them in their Rust code. Install Add this

Psychedelic 26 Nov 28, 2022
MimiRust - Hacking the Windows operating system to hand us the keys to the kingdom with Rust.

MimiRust - Hacking the Windows operating system to hand us the keys to the kingdom with Rust. MimiRust is a program based on the wdigest attack vector

Thotty 0 Nov 29, 2022
simple multi-threaded port scanner written in rust

knockson simple multi-threaded port scanner written in rust Install Using AUR https://aur.archlinux.org/packages/knockson-bin/ yay -Syu knockson-bin M

Josh MΓΌnte 4 Oct 5, 2022
Rust TLS/SSL certificate expiration date from command-line checker

Rust TLS/SSL certificate expiration date from command-line checker

Jose Bovet Derpich 9 Nov 9, 2022
Lightweight slowloris (HTTP DoS) implementation in Rust.

slowlorust Lightweight slowloris (HTTP DoS) implementation in Rust. Slowloris is a denial-of-service attack program which allows an attacker to overwh

Michael Van Leeuwen 6 Sep 29, 2022
A simple port scanner built using rust-lang

A simple port scanner built using rust-lang

Krisna Pranav 1 Nov 6, 2021
Safe Rust interface to the Vulkan API.

Magma: A strictly typed Vulkan API interface. Magma is a strictly typed Rust interface for the vulkan API. This means that whenever possible, the well

null 1 Oct 11, 2022
A rust program to bruteforce ZIP, PDF and some popular hashes.

Veldora A program to bruteforce zips, pdfs and some popular hashes. This is basically a rust version of bruttle, but a lot faster. Installation: git c

Aquib 30 Dec 28, 2022
BGPKIT Parser aims to provides the most ergonomic MRT/BGP/BMP message parsing Rust API.

BGPKIT Parser aims to provides the most ergonomic MRT/BGP/BMP message parsing Rust API.

BGPKIT 46 Dec 19, 2022