unfuck is a utility and library for deobfuscating obfuscated Python 2.7 bytecode

Overview

unfuck

Have fucked Python 2.7 bytecode? Let's unfuck it.

Overview

unfuck is a utility and library for deobfuscating obfuscated Python 2.7 bytecode. It is essentially a reimplementation of the Python VM with taint tracking. Some of the things unfuck can do:

  1. Remove opaque predicates
  2. Dead code elimination
  3. Restore some lost function names
  4. Cleanup obfuscated variable names

#1 and #2 are the two biggest items that Python decompilers trip over when attempting to reconstruct original Python source code.

unfuck basically makes your bytecode go from this to this:

Obfuscated code Deobfuscated code

Or from this to this:

Obfuscated vs deobfuscated code hex dump

Yes, these are real-world examples.

Useful Wiki Resources

Usage

unfuck can either be used as a library or a command-line utility.

unfuck 0.2.0

USAGE:
    unfuck [FLAGS] [OPTIONS]   [graphs-dir] [SUBCOMMAND]

FLAGS:
        --dry        Dry run only -- do not write any files
    -g               Enable outputting code graphs to dot format
    -h, --help       Prints help information
    -q               Disable all logging
    -V, --version    Prints version information
    -v               Enable verbose logging

OPTIONS:
        --decompiler     Your favorite Python 2.7 bytecode decompiler. This program assumes the decompiler's
                                     first positional argument is the file to decompile, and it prints the decompiled
                                     output to stdout [env: UNFUCK_DECOMPILER=]  [default: uncompyle6]

ARGS:
        Input obfuscated file
                  Output file name or directory name. If this path is a directory, a file will be
                               created with the same name as the input. When the `strings-only` subcommand is
                               applied, this will be where the output strings file is placed
                   An optional directory for graphs to be written to [default: .]

SUBCOMMANDS:
    help            Prints this message or the help of the given subcommand(s)
    strings-only

To unfuck a single file:

# deobfuscated.pyc can also be a directory
unfuck obfuscated.pyc deobfuscated.pyc

You can also provide additional flags to dump strings to a file, or dump dot graphs that can be viewed in graphviz:

# -g is for printing graphs
unfuck -g obfuscated.pyc deobfuscated.pyc
# use the strings-only subcommand for dumping just dumping strings -- no deobfuscation is performed
unfuck deobfuscated.pyc ./strings.csv strings-only

Building

unfuck requires Python 2.7 in your system's PATH. After ensuring it's present, you should be able to just cargo build. If for some reason the correct interpreter cannot be found, try setting the PYTHON_SYS_EXECUTABLE env var to your Python 2.7 interpreter path.

Installing

cargo install --force unfuck

Library Usage

NOTE: unfuck was not originally designed with library usage in mind, and therefore brings its own multithreading platform (in this case, Rayon).

Usage is fairly straightforward:

::new(pyc_contents); let deobfuscator = if enable_graphs { deobfuscator.enable_graphs() } else { deobfuscator }; let deobfuscated_code = deobfuscator.deobfuscate()?; let mut deobfuscated_file = File::create("deobfuscated.pyc")?; deobfuscated_file.write_all(&magic.to_le_bytes()[..])?; deobfuscated_file.write_all(&moddate.to_le_bytes()[..])?; deobfuscated_file.write_all(deobfuscated_code.data.as_slice())?; ">
use std::convert::TryInto;
use std::fs::File;

let mut pyc_contents = vec![];
let pyc_file = File::open("obfuscated.pyc")?;
pyc_file.read_to_end(&mut pyc_contents)?;

// magic/moddate are specific to the PYC header and are required to be
// a valid PYC file
let magic = u32::from_le_bytes(pyc_contents[0..4].try_into().unwrap());
let moddate = u32::from_le_bytes(pyc_contents[4..8].try_into().unwrap());

let pyc_contents = &pyc_contents[8..];

// Use a standard Python 2.7 opcode table
let deobfuscator = unfuck::Deobfuscator::<pydis::opcode::py27::Standard>::new(pyc_contents);
let deobfuscator = if enable_graphs {
    deobfuscator.enable_graphs()
} else {
    deobfuscator
};

let deobfuscated_code = deobfuscator.deobfuscate()?;

let mut deobfuscated_file = File::create("deobfuscated.pyc")?;
deobfuscated_file.write_all(&magic.to_le_bytes()[..])?;
deobfuscated_file.write_all(&moddate.to_le_bytes()[..])?;
deobfuscated_file.write_all(deobfuscated_code.data.as_slice())?;

greetz

gabe_k, yrp, lpcvoid, folks from the WD disc, squif, ian, pie doom, saruhan

You might also like...
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

QuickCheck bug hunting in Rust standard library data structures

BugHunt, Rust This project is aiming to provide "stateful" QuickCheck models for Rust's standard library. That is, we build up a random list of operat

Cross-platform async library for system information fetching 🦀
Cross-platform async library for system information fetching 🦀

heim Cross-platform library for system information fetching heim is an ongoing attempt to create the best tool for system information fetching (ex., C

A simple rust library for working with ZIP archives

rust-zip A simple rust library to read and write Zip archives, which is also my pet project for learning Rust. At the moment you can list the files in

Memory hacking library for windows.

Memory hacking library for windows.

An attempt to rewrite lite-client for TON Blockchain in Rust using ton-labs-adnl library.

An attempt to rewrite lite-client for TON Blockchain in Rust using ton-labs-adnl library.

A new shellcode injection technique. Given as C++ header, standalone Rust program or library.
A new shellcode injection technique. Given as C++ header, standalone Rust program or library.

FunctionStomping Description This is a brand-new technique for shellcode injection to evade AVs and EDRs. This technique is inspired by Module Stompin

Extended precision integer Rust library. Provides signed/unsigned integer 256 to 2048.

Extended precision integer Rust library. Provides signed/unsigned integer 256 to 2048.

An R interface to Rust's h3o library
An R interface to Rust's h3o library

h3o h3o is a system-dependency free package to interact with the H3 Geospatial Indexing system by Uber. h3o utilizes the Rust library h3o with is a pu

Comments
  • Unable to install on Windows 10

    Unable to install on Windows 10

    I ran:

    cargo install --force unfuck
    

    And get the following: error: failed to run custom build command for python27-sys v0.5.2

    Caused by: process didn't exit successfully: C:\Users\Owner\AppData\Local\Temp\cargo-installjv6TdT\release\build\python27-sys-3402b30bc412a50e\build-script-build (exit code: 101) --- stderr thread 'main' panicked at 'called Result::unwrap() on an Err value: "No python interpreter found of version 2.7"', C:\Users\Owner.cargo\registry\src\github.com-1ecc6299db9ec823\python27-sys-0.5.2\build.rs:453:65 note: run with RUST_BACKTRACE=1 environment variable to display a backtrace warning: build failed, waiting for other jobs to finish... error: failed to compile unfuck v0.3.0, intermediate artifacts can be found at Does Python 2.7 need to be in your path even to install it through cargo? I saw that listed in the building section, but wasn't sure if you needed it simply to install it too.

    In addition, does it matter how its added to your path? For example, I have Python 3.7, 3.8, 3.9, and 3.10 installed currently. I call 3.10 with just Python, but 3.9 with python3.9. Would having Python 2.7 added to my path as python2.7 mess up the functionality?

    opened by TheQuinbox 1
Owner
Lander Brandt
Lander Brandt
Decryption utility for Yaesu ham radio firmware images

porkchop Decryption utility for Yaesu ham radio firmware images. Background Yaesu provides a firmware update utility for their ham radios that contain

Lander Brandt 20 Dec 29, 2022
cert_installer - a utility that adds a CA certificate to Android's System Trust Store

cert_installer is a utility that adds a CA certificate to Android's System Trust Store by overwriting the /system/etc/security/cacerts directory with a tmpfs mount. Changes made to the System Trust Store is not persistant across reboots.

Terry Chia 5 Apr 11, 2022
Xori is an automation-ready disassembly and static analysis library for PE32, 32+ and shellcode

Xori - Custom disassembly framework Xori is an automation-ready disassembly and static analysis library that consumes shellcode or PE binaries and pro

ENDGAME 712 Nov 28, 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
Advanced Fuzzing Library - Slot your Fuzzer together in Rust! Scales across cores and machines. For Windows, Android, MacOS, Linux, no_std, ...

LibAFL, the fuzzer library. Advanced Fuzzing Library - Slot your own fuzzers together and extend their features using Rust. LibAFL is written and main

Advanced Fuzzing League ++ 1.2k Jan 6, 2023
Mundane is a Rust cryptography library backed by BoringSSL that is difficult to misuse, ergonomic, and performant (in that order).

Mundane Mundane is a Rust cryptography library backed by BoringSSL that is difficult to misuse, ergonomic, and performant (in that order). Issues and

Google 1.1k Jan 3, 2023
Linux anti-debugging and anti-analysis rust library

DebugOff Library Linux anti-analysis Rust library The goal of this library is to make both static and dynamic (debugging) analysis more difficult. The

null 65 Jan 7, 2023
A rust library for sharing and updating arbitrary slices between threads, optimized for wait-free reads

atomicslice A Rust library for thread-safe shared slices that are just about as fast as possible to read while also being writable. Overview Use Atomi

Tim Straubinger 5 Dec 6, 2023
Kepler is a vulnerability database and lookup store and API currently utilising National Vulnerability Database and NPM Advisories as data sources

Kepler — Kepler is a vulnerability database and lookup store and API currently utilising National Vulnerability Database and NPM Advisories as data so

Exein.io 101 Nov 12, 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