It’s already a common knowledge that merely rebuilding binaries could be a good way to attempt to bypass many AV solutions. Here’s a good illustration of exactly that case from our recent penetration testing engagement. Here’s the scenario:

After spending some time in client’s internal network, we spotted a machine with misconfigured JMX endpoint:

Vulnerable JMX endpoint

This was easily turned into RCE on the affected machine:

RCE

At the first look escalating to SYSTEM seemed straightforward, thanks to JuicyPotato tool and possessed permission set:

Permission set

However during attack preparation and usual OPSEC checks it became evident that prebuilt version of JuicyPotato tool is not ready for operational usage:

JuciyPotato VirusTotal discovery ratio

So before using JuicyPotato we performed following steps:

  1. Changed main source code file to something else (SoczystyKartofel in our case :))
  2. Removed printf calls printing JuicyPotato string.
  3. Renamed PotatoAPI structure to something else.
  4. Changed all includes files to lowercase (i.e. Windows.h -> windows.h) as required by MinGW compiler.
  5. Built new JuicyPotato binary from modified sources.

For building we used Zig compiler as it is capable of cross-compiling of C/C++ code for Windows platforms (it uses MinGW for that):

$ zig c++ -target x86_64-windows-gnu -std=c++17 IStorageTrigger.cpp SoczystyKartofel.cpp LocalNegotiator.cpp -luuid -lole32 -DUNICODE -D_UNICODE -lws2_32 -lsecur32 -o juicyPotato

Alternatively following build.zig could be used for building:

const std = @import("std");

pub fn build(b: *std.build.Builder) void {
    const target = b.standardTargetOptions(.{});
    const mode = b.standardReleaseOptions();

    const exe = b.addExecutable("<binName>", null);
    exe.setTarget(target);
    exe.setBuildMode(mode);
    exe.linkSystemLibraryName("c");
    exe.linkSystemLibraryName("c++");
    exe.linkSystemLibraryName("uuid");
    exe.linkSystemLibraryName("ws2_32");
    exe.linkSystemLibraryName("secur32");
    exe.linkSystemLibraryName("ole32");
    exe.addCSourceFiles(&.{
        "IStorageTrigger.cpp",
        "SoczystyKartofel.cpp",
        "LocalNegotiator.cpp",
    }, &.{
        "-std=c++17",
        "-DUNICODE",
        "-D_UNICODE",
    });
    exe.strip = true;
    exe.install();
}

and starting build process would be done with following command:

$ zig build -Drelease-small=true -Dtarget=x86_64-windows-gnu

And voila, after those trivial modifications, the new AV discovery ratio for the JuicyPotato binary looked much better:

Improved discovery ratio