Giter Site home page Giter Site logo

muddy-waters's Introduction

muddy

muddy is a static string obfuscation library, designed to provide an easy way of avoiding simple static binary analysis tools such as strings or YARA rules. It functions by encrypting texts at buildtime, and decrypting them lazily at runtime.

Usage & Examples

use muddy::{m, muddy_init};

muddy_init!();

println!("{}", m!("My highly obfuscated text"));
println!("{}", "My non obfuscated static str - ripgrep me");

Compile this example and grep the binary for obfuscated:

cargo b --example simple

strings ./target/debug/examples/simple | grep obfuscated
Only the second nonobfuscated line should appear.

muddy primarily provides the exported m!(), #[muddy], and muddy_all! { } macros, all which take text as input and encrypt it. The muddy_init!() macro provides the scaffolding for decrypting the strings at runtime and should be placed at the root of the user's crate.

These macros can be used as an in-place text replacement with m!("my text"):

use muddy::{muddy_init, m};

muddy_init!();

println!("{}", m!("my plaintext"));

As an annotated &'static str with the [muddy] attribute:

use muddy::{muddy, muddy_init};

muddy_init!();

#[muddy]
static MY_STR: &str = "my plaintext";

Or as an invocation around multiple annotated &'static strs with [muddy_all]:

use muddy::{muddy_all, muddy_init};

muddy_init!();

muddy_all! {
   pub static MY_STR: &str = "my plaintext";
   pub static MY_SECOND_STR: &str = "my second plaintext";
   static MY_THIRD_STR: &str = "my module-specific third plaintext";
}

By default, muddy will encrypt the static strings with the [chacha20poly1305] implementation, and embed the key inside the binary.

To avoid hardcoding the deobfuscation key into your binary, you may use:

use muddy::{m, muddy_init};

muddy_init!("env");

// If you build your program with `muddy_init!("env")`,
// the deobfuscation key env variable and deobfuscation key
// will be printed out to stderr:  
// `MUDDY='D47A372C13DEFED74FD3B9B4C741C355F9CB2C23C43F98ADE2C02FD50CA55C3D'`

// This key needs to be provided at runtime else the program will panic.  
// `MUDDY='D47A372C13DEFED74FD3B9B4C741C355F9CB2C23C43F98ADE2C02FD50CA55C3D' ./target/debug/examples/env`
    println!("{}", m!("My highly obfuscated text"));
    println!("{}", "My non obfuscated static str - ripgrep me");

If muddy_init!("env") is set, the MUDDY (by default) env variable will be checked at runtime for the key and the program will panic if it's not found.

You can also set your own env key identifier at buildtime through MUDDY:
This: MUDDY='MY_KEY_NAME_2' cargo b --example env
prints: MY_KEY_NAME_2='FD5B85045B5278F5EDA567AD7C58EB56934BD8D7432C878B1AB6090052A64080'

muddy_init!

muddy_init!() can take one of two values:

  • muddy_init!("embed")
  • muddy_init!("env")

If no value is provided, the macro defaults to the "embed" configuration.
If "env" is provided, you may also set the env key identifier as the second field: muddy_init!("env", "MY_KEY")

Note on obfuscation and encryption

This crate does not provide any form of real encryption. It only makes the task of understanding strings in your binary more difficult. Obfuscation is not security.

This crate also does not obfuscate any debug symbols you may have. Profile settings such as

# inside Cargo.toml

[profile]
strip = true
panic = "abort"
# ...

and more can be found in the cargo reference.

Macro expansion

To check what this macro expands to:

  • install cargo expand
  • run: cargo expand -p muddy --example env

Next steps:

  • handle #![no_std] environments
  • check safety with leaking mut statics
  • check proc macro testing suites

Disclaimer

This library is developed with the sole intention of providing a tool to challenge and educate cybersecurity professionals. It is not intended for any malicious or unlawful activities. The creators and contributors of this library do not endorse, encourage, or support the use of this tool for any illegal purposes.

Similar/related projects

License

Dual-licensed under Apache 2.0 and MIT terms.

muddy-waters's People

Contributors

orph3uslyre avatar mrauhu avatar

Stargazers

Kingtem avatar Dobo_J avatar  avatar  avatar aweNousaku avatar Koray avatar Rick avatar shockpast avatar  avatar Adan Alvarado avatar Daniel Gomes-Sebastiao avatar Ivan Cordoba avatar Markus Mayer avatar Mário Monteiro avatar Jeremy Jackson avatar  avatar  avatar Francesco Pira avatar Vitaliy Yermolenko avatar Simone Ragusa avatar Mert Sefa AKGUN avatar raf avatar Eggrror404 avatar Luis Quiñones avatar  avatar astrolemonade avatar  avatar  avatar Murat Genç avatar Yuki Kishimoto avatar Thierry Berger avatar Hubert avatar Matteo Bigoi avatar blong avatar Berkus Decker avatar alireza faghani avatar  avatar Jan Margeta avatar ffred avatar Irine Kokilashvili avatar Mathys Lv avatar Volkan Yıldız avatar  avatar dunxen avatar fan-tastic-z avatar Yuta Yamaguchi avatar Michael Harding avatar Tao Jianhang avatar Orhun Parmaksız avatar Hendrik Sollich avatar Madeline Sparkles avatar Félix Lescaudey de Maneville avatar mehrzaden avatar dubs3c avatar  avatar Nicolas Vincent avatar  avatar AVA avatar  avatar hirak0 avatar  avatar guly avatar x86 avatar Michael Eder avatar Yura Markin avatar Lina avatar hangrum avatar  avatar Tu Anh Dao avatar Oğuzhan Akkaya avatar

Watchers

 avatar

muddy-waters's Issues

add tests & basic CI/CD

add testing

  • there are currently no tests or CI/CD to speak of, and tests are great
  • at the very least some of the basic examples can be added as tests with the linux/macos/windows targets to avoid issues likes #2 down the line

resources

  • excellent blog post with proc_macro testing examples here

Error build on Windows: could not find `unix` in `os`

Hello @orph3usLyre.

I found a bug when building a project with muddy dependency on Windows:

   |
 3 | muddy_init!();
   | ^^^^^^^^^^^^^
   | |
   | could not find `unix` in `os`
   | in this macro invocation
   |
  ::: ...\muddy_macros-0.2.0\src\lib.rs:88:1
   |
88 | pub fn muddy_init(input: TokenStream) -> TokenStream {
   | ---------------------------------------------------- in this expansion of `muddy_init!`
   |

The source of bug is an import of std::os::unix::ffi::OsStrExt without config:

quote! {
use muddy::{GenericArray, KeyInit, Lazy, ChaCha20Poly1305, Key, Aead, U32, Nonce};
pub use muddy::{LazyStr, FromHex};
use std::os::unix::ffi::OsStrExt;
}

Possible solution is:

     #[cfg(unix)]
     use std::os::unix::ffi::OsStrExt;
     #[cfg(wasi)]
     std::os::wasi::ffi::OsStrExt;
     #[cfg(windows)]
     std::os::windows::ffi::OsStrExt;

Please, see the OsStrExt trait implementation: https://doc.rust-lang.org/std/index.html?search=OsStrExt.

Best wishes,
Sergey.

stabilize API for different obfuscation modes

context

  • this library currently provides 2 primary "modes" for obfuscation functionality:
    1. the "embedded" mode, which places the deobfuscation key inside the user's binary
      • less secure since the key is part of the binary
      • does not require any user interaction for the user binary to work
    1. the "env" mode, which requires the user to provide the deobfuscation key at runtime
      • slightly more secure since the key needs to be discovered first/brute forced
      • requires user interaction at runtime for the binary to run

todo:

  1. I would like to stabilize the API of the different library "modes" since I'm not currently happy with the muddy_init("embed") / muddy_init!("env") solution. Additionally, setting a user's custom env variable identifier is not extremely clear.
  2. I would also like to begin thinking about if this library should offer different types of encryption. Currently, we use the ChaCha20-Poly1305 cipher implementation. Should this library offer other encryption methods for its strings or simply an opinionated decision of the cipher that should be used? Is it even useful to have other types of encryption?

could not find `windows` in `os`

My code on Windows:

use muddy::{m, muddy_init};
muddy_init!();

fn main() {
    println!("{}", m!("My highly obfuscated text"));
    println!("{}", "My non obfuscated static str - ripgrep me");
}

Run cargo build --target x86_64-unknown-linux-musl

error[E0433]: failed to resolve: could not find `windows` in `os`                                                                                              
   --> src\main.rs:2:1
    |
2   | muddy_init!();
    | ^^^^^^^^^^^^^ could not find `windows` in `os`
    |
note: found an item that was configured out
   --> C:\Users\myname\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library/std/src/os/mod.rs:53:9
    |
53  | pub mod windows {}
    |         ^^^^^^^
note: found an item that was configured out
   --> C:\Users\myname\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library/std/src/os/mod.rs:100:9
    |
100 | pub mod windows;
    |         ^^^^^^^
    = note: this error originates in the macro `muddy_init` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0433`.                                                                                            
error: could not compile `test_muddy` (bin "test_muddy") due to 1 previous error    

Expand macros:

pub mod muddy_internal {
    use muddy::{GenericArray, KeyInit, Lazy, ChaCha20Poly1305, Key, Aead, U32, Nonce};
    pub use muddy::{LazyStr, FromHex};
    use std::os::windows::ffi::OsStrExt;

    static KHJU9SXTVNMVXTDQY: &'static [u8; 32] = b"s|i\xbc\xa88\x9et\x18[}\xb1\xbdn\xdfP\xce\xe0\rH\xf47\x9am,{\xa6\xe4\xe2=\x9c\x15";
    static JUNK: &'static [u8; 32] = b"\xff\x89 \x9d!\xb2\x0ef\xb0\x87t)\xf6\x8e\x01\xc8\xee^\xca2:Z\x1a\x1a\x92\xc0\xc7\xc4(\x03I ";
    static PMBKW4TKD2HJK04P8: Lazy<ChaCha20Poly1305> = Lazy::new(|| {
        let mut key = KHJU9SXTVNMVXTDQY.clone();
        key.iter_mut().zip(JUNK.iter()).for_each(|(b, k)| *b ^= k);
        ChaCha20Poly1305::new(Key::from_slice(&key))
    });

    pub fn decrypt(encrypted: &[u8], nonce: &[u8]) -> String {
        let nonce = Nonce::from_slice(nonce);
        let plaintext = PMBKW4TKD2HJK04P8.decrypt(nonce, encrypted).unwrap();
        String::from_utf8(plaintext).unwrap()
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.