1

I am trying to write a program in C that would be able to call certain binaries (ex. lsof, netstat) with options. The purpose of this program is to collect forensic data from a computer, while at the same time this program should not use the binaries of the computer under analysis as they might be compromised. As a result it is required the certified/uncompromised binaries (ex. lsof, netstat -antpu etc) already to be embedded in a C program or to be called by the C program stored in a usb drive for example.

  1. Having for example the binary of the "ls" command I created an object file using the linker as follows:
    $ ld -s -r -b binary -o testls.o bin-x86-2.4/ls
  1. Using the following command I extracted the following entry points from the object file
    $ nm testls.o

    000000000007a0dc D _binary_bin_x86_2_4_ls_end
    000000000007a0dc A _binary_bin_x86_2_4_ls_size
    0000000000000000 D _binary_bin_x86_2_4_ls_start
  1. The next step would be to call the "function" from the main program with some options that I might need for example "ls -al". Thus I made a C program to call the entry point of the object file.

  2. Then I compiled the program with the following gcc options

    gcc -Wall -static testld.c testls.o -o testld

This is the main program:

#include <stdio.h>

extern int _binary_bin_x86_2_4_ls_start();

int main(void)  
{
    _binary_bin_x86_2_4_ls_start();
    return 0;
}

When I run the program I am getting a segmentation fault. I checked the entry points using the objdump in the testld program and the linking seems to be successful. Why then I am getting a segmentation fault? I still need also to call "ls" with options. How I could do this, i.e. call the "function" with the arguments "-al".

Thank you.

  • 1
    This is not as easy as it sounds, as storing binary data usually ends up in the data segment, which is not executable. You have to rellocate it into an executable segment first yourself and create a new process around that segment so it can be called in an `exec`-like way. In short, you have to reimplement the dynamic loader of the operating system. – Some programmer dude Sep 03 '19 at 18:30
  • I'd be surprised if this isn't a [duplicate of this question](https://stackoverflow.com/questions/42235175/how-do-i-add-contents-of-text-file-as-a-section-in-an-elf-file) - or a similar one.... – Andrew Henle Sep 03 '19 at 18:31
  • _[THIS](https://codeplea.com/embedding-files-in-c-programs)_ may, or may not address all of your needs, but it will likely answer a few questions about feasibility. – ryyker Sep 03 '19 at 18:40
  • 2
    The easiest thing to do might be to embed the binary, then, when it is needed, write it to a file and use one of the `exec` routines to execute that file. Or simply copy your own other binaries over when you are copying over this program. But this is likely an X-Y problem: To collect forensic data from a compromised system, you should not run that system at all. You should copy data directly from its storage (e.g., remove its storage and read it with another computer, or, if the hardware is not completely untrusted, boot it in “target disk mode” [a Mac feature] and read the data). – Eric Postpischil Sep 03 '19 at 18:44
  • I have taken note of your forensic scheme and prepared a kernel mode rootkit. – Joshua Sep 03 '19 at 18:45
  • What do you mean Joshua? – elsiesemico Sep 03 '19 at 19:35
  • Using certified binaries actually won't help as much as you think. The kernel ABIs are simply going to lie to everybody who doesn't know the secret handshake. – Joshua Sep 04 '19 at 01:28
  • Joshua can you provide any references regarding the concept of Kernel ABIs and how these can be compromised? – elsiesemico Sep 08 '19 at 04:30

1 Answers1

0

The ELF header of a binary isn't a function. You can't call it. If you could (like in some ancient binary formats) it would be a really bad idea because it would never return.

If you want to run another program midstream do this:

int junk;
pid_t pid;
if (!(pid = fork())) {
    execl("ls", "/bin/ls", ...); /* this results in running ls in current directory which is probably what you want but maybe you need to adjust */
    _exit(3);
}
if (pid > 0) waitpid(pid, &junk, 0);

Error handling omitted for brevity.

In your case, you should ship your own copies of your binaries alongside your program.

Joshua
  • 40,822
  • 8
  • 72
  • 132
  • The question states they do not want to use the binaries on the system, so `execl("/bin/ls"…)` is not an acceptable solution. – Eric Postpischil Sep 03 '19 at 18:40
  • 1
    @EricPostpischil: I see. I made a slight fix. He can ship the binaries as files and call them normally. – Joshua Sep 03 '19 at 18:42