Skip to content
jm33-m0 edited this page Jan 22, 2025 · 10 revisions

DLL / Shared Library Agent

From version v1.49.0, emp3r0r supports DLL agent and Linux shared object agent. This is a new type of agent that can be loaded into a target process, and it's more stealthy than the traditional agent.

When generating a DLL agent, you need to set payload_type to windows_dll or linux_so and run it normally. You will get a DLL file to deliver to the target machine. The DLL agent can be loaded into a target process using rundll32 or regsvr32, and it will connect back to the C2 server.

The DLL will be huge, you can pack it with upx or use your stager to compress it before delivery.

How to use

Call main function exported by the DLL/SO.

Linux Shared Object

#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
  if (argc != 2) {
    fprintf(stderr, "Usage: %s <path_to_shared_object>\n", argv[0]);
    return EXIT_FAILURE;
  }

  const char *so_path = argv[1];
  void *handle = dlopen(so_path, RTLD_LAZY);
  if (!handle) {
    fprintf(stderr, "Error opening shared object: %s\n", dlerror());
    return EXIT_FAILURE;
  }

  void (*main_func)();
  *(void **)(&main_func) = dlsym(handle, "main");
  if (!main_func) {
    fprintf(stderr, "Error finding main function: %s\n", dlerror());
    dlclose(handle);
    return EXIT_FAILURE;
  }

  main_func();

  dlclose(handle);
  return EXIT_SUCCESS;
}

Windows DLL

This is a very basic example of how to use teh DLL agent. You can also use rundll32 to load the DLL into a target process.

package main

import (
 "C"
 "fmt"
 "os"
 "plugin"
)

func main() {
 if len(os.Args) < 2 {
  fmt.Fprintf(os.Stderr, "Usage: %s <path_to_shared_object> [args...]\n", os.Args[0])
  os.Exit(1)
 }

 soPath := os.Args[1]

 // Load the shared object file
 p, err := plugin.Open(soPath)
 if err != nil {
  fmt.Fprintf(os.Stderr, "Error loading shared object: %s\n", err)
  os.Exit(1)
 }

 // Lookup the 'main' function
 symMain, err := p.Lookup("main")
 if err != nil {
  fmt.Fprintf(os.Stderr, "Error finding 'main' in shared object: %s\n", err)
  os.Exit(1)
 }

 // Assert the type of the 'main' function
 soMain, ok := symMain.(func(argc int, argv []string) int)
 if !ok {
  fmt.Fprintf(os.Stderr, "Invalid 'main' function signature\n")
  os.Exit(1)
 }

 // Prepare arguments for the SO's main function
 soArgc := len(os.Args) - 1
 soArgv := os.Args[1:]

 // Call the main function of the shared object
 exitCode := soMain(soArgc, soArgv)

 os.Exit(exitCode)
}