Reverse Engineering

Reverse engineering is the process of analyzing a program, or system to understand its structure, function, and behavior.

It often means getting back the original code/system using disassembling, decompiling, or similar methods.

It can be used to understand how a malware works πŸ›‘οΈ or to find vulnerabilities in a program/system in a black-box assessment πŸ’₯.

For simple programs, we might be able to get the information we need using the commands below:

  • strace: see every system call
  • strings: extract every readable string, may not be installed

Java Reverse Engineering

JAR application

attacking_common_applications

You can extract a JAR archive using archive tools or:

$ jar xf xxx.jar

You can also create a JAR archive using archive tools or:

$ jar -cvf ../xxx.war *
$ jar -cmf ./META-INF/MANIFEST.MF ../xxx.jar *

If you plan to edit the JAR, you may have to remove every checksum from the MANIFEST.MF along with .RSA/.SF to by-pass integrity checks. ⚠️ Note that MANIFEST.MF must ends with a blank line.

Before you modify a file, you need to create a raw copy in which you will inject .class before bundling them back to a JAR:

$ mkdir raw && cd raw
$ jar xvf ../xxx.jar && cd ..

Now, you can edit a file and transfer its compiled .class to "raw":

$ javac -cp xxx.jar source_code/path/to/file.java
$ cp -r source_code/path/to/*.class raw/path/to/file

Once you are done, pack "raw" back to a JAR:

$ jar -cmf raw/META-INF/MANIFEST.MF xxx.jar raw

Java jd - Decompiler

attacking_common_applications blocky

You can use jd-gui (13.2k ⭐) to reverse a Java application. Run jd-gui, and oad the JAR in it. You can then either:

  • Explore the reversed sources from jd-gui
  • Use File> Save all sources and read/modify them in your editor

Java - Other Decompilers

Other well-known decompilers:


.NET Reverse Engineering

.NET De4Dot - Decompiler

attacking_common_applications

You can use de4dot (6.6k ⭐, 2020 πŸͺ¦) to reverse your binary. On Windows, drag and drop your binary onto the de4dot executable.


.NET dnSpy - Debug/Editor

attacking_common_applications

You can use dnSpy (24.8k ⭐, 2020 πŸͺ¦) to explore .NET source code.

.NET - Other Decompilers

Other well-known decompilers:


Windows Binaries

Windows x64dbg debugger

attacking_common_applications introduction_to_malware_analysis

You can use x64dbg (42.5k ⭐) to debug binaries.

  • You can navigate to options to define the breakpoints. For instance, uncheck everything except Exit Breakpoint.
  • The memory map tab can be used to find stuff like memory-mapped files (a file mapped to a memory region like a buffer).
    • Double-click on an entry to see its bytes
    • You may recognize a file from the magic code bytes
    • Right-click on an address to dump its contents to a file
  • Use 'Search for > Current Module > String references' to see strings and their address. You can double-click on an address to navigate to it (see also: Right-click > 'Toggle Breakpoint.')
  • Place the cursor on an instruction, and press 'Spacebar' to edit it.
  • Use CTRL+P to save the patched instructions.

➑️ See also: x64dbg unpack malware and OllyDbg.


Linux Binaries

getting_started questionnaire reg elf_x86_0_protection elf_x86_basic

Linux GDB Disassembly

stack_based_buffer_overflows_linux_x86 attacking_common_applications

You can use peda and GDB.

$ git clone https://github.com/longld/peda.git ~/peda
$ echo "source ~/peda/peda.py" >> ~/.gdbinit
$ echo "set disassembly-flavor intel" >> ~/.gdbinit
$ gdb -q xxx.bin
(gdb) disas main
(gdb) # refer to GDB documentation
(gdb) run

Linux Tracers

mustacchio

Linux commands strace and ltrace are very helpful to identify system and library calls in a program, which is helpful to reverse it.

$ strace xxx.bin
$ ltrace xxx.bin

Linux Radare Disassembly

Radare (19.2k ⭐) is similar to GDB, but it somewhat easier to use if we only need to disassemble the code.

$ rabin2 -I xxx.bin # get information
$ rabin2 -z xxx.bin # list strings
$ r2 -A xxx.bin     # disassemble
(r2) pdf @main

Boomerang

boomerang (0.3k ⭐) that is somewhat able to reverse x86 binaries in an unreadable uncompilable C file.

Docker Installation

Save the code below in a dockerfile and run docker build -t boomrangcli:latest . to build the docker image.

FROM ubuntu:22.04

# From https://github.com/BoomerangDecompiler/boomerang#building-on-linux
# [CHANGE] qt5-default => libqt5core5a libqt5gui5 libqt5widgets5 qtbase5-dev
RUN apt-get update && \
    apt-get install -y git build-essential cmake \
    qtbase5-dev libqt5core5a libqt5gui5 libqt5widgets5 \
    libcapstone-dev flex bison

# [CHANGE] Used /opt
WORKDIR /opt
RUN git clone https://github.com/BoomerangDecompiler/boomerang.git
WORKDIR /opt/boomerang/build

RUN cmake .. && make -j$(nproc) && make install

# Remove the build folder
RUN rm -rf /opt/boomerang

# Don't run the tool as root
RUN useradd -ms /usr/sbin/nologin boomerang
WORKDIR /builds/
RUN chown -R boomerang:boomerang /builds/
USER boomerang

ENTRYPOINT ["/usr/local/bin/boomerang-cli"]

For instance to decompile ch1.bin:

$ docker run -it -v $(pwd):/builds boomrangcli:latest ch1.bin

Code Obfuscation

javascriptdeobfuscation javascript_obfuscation_1 javascript_obfuscation_2 javascript_obfuscation_3 javascript_native_code ast_deobfuscation

Code obfuscation is an automated process to make the code less-readable for humans. A simple example would be by replacing variables names with less readable names such as _0x565.

Code obfuscation doesn't impact the program functionality, but it may impact its performance: obfuscated code is usually slower.

UPX-packed Malware

Ultimate Packer for eXecutables (UPX) is a popular packer for malware.

$ upx -d -o unpacked_xxx.exe xxx.exe

Javascript Obfuscation

A few obfuscators for JavaScript:

You may try unpacker to unpack code while you can try relative.im or deobfuscate.io to undo simple obfuscation.

Native code or using a abstract syntax tree are also possible. You can decode an AST using escodegen (2.6k ⭐).

const { generate } = require('escodegen');
const ast = {}; // add the JSON AST here
const generatedCode = generate(ast);
console.log(generatedCode);

πŸ‘» To-do πŸ‘»

Stuff that I found, but never read/used yet.

Invoke-DOSfuscation> SET COMMAND type <path>
Invoke-DOSfuscation> encoding
Invoke-DOSfuscation\Encoding> 1

Analysis

$ bashfuscator -c 'cat /etc/passwd'
$ bashfuscator -c 'cat /etc/passwd' -s 1 -t 1 --no-mangling --layers 1

Common tools