DLL injection in windows is a common and very well-known technique which is seen in windows malware binaries, but ever wondered how this approach can be applied into LINUX systems, that is what we will be looking in this blog. While doing my research on LINUX malwares tactics and techniques I came to know about this technique that how on LINUX platform a shared library could be injected into a running process. Well, the concept is not too complex for the one who has a little background in C and assembly and moreover analysing the malicious software. Now let’s see how the code and this technique works.

Ptrace system call provides a means by which one process can be controlled by other including its observation and execution, this is what we will be using for injection. Other injection method includes LD_PRELOAD, which we will cover in future blog. Ptrace offers a number of options to the user, which are:

PTRACE_ATTACH – Allows one process to attach itself to another for debugging, pausing the remote process.

PTRACE_PEEKTEXT – Allows the reading of memory from another process address space.

PTRACE_POKETEXT – Allows the writing of memory to another process address space.

PTRACE_GETREGS – Reads the current set of processor registers from a process.

PTRACE_SETREGS – Writes to the current set of processor registers of a process.

PTRACE_CONT – Resumes the execution of an attached process.

Along with Ptrace we will focus on resolving addresses of below functions:

1.dlopen

2.dlsym

3.malloc

4.free

First, we resolve the addresses of the required functions because as we know that due to security reasons in every process address of the libraries are randomized. Below snippet shows that clearly:

Function addresses difference with respect to libc library of our own process:

Function addresses in the target process (i.e. first we fetch the address of libc then the required function’s addresses with the help of the above result of differences) and also libc’s address corresponding to the target process was resolved by searching the target process’s pid in /proc/%d/maps as shown below:

getfunaddr snippet:

RTLD_LAZY has been used for Lazy-Linking (i.e. resolving the addresses at runtime).dlopen and dlsym in LINUX are equivalent to LoadLibrary and GetProcAddress in windows respectively.

Now we will fetch the value of the registers from the target process, for that we have snippet below:

Clearly visible that first we fetched the values of registers using ptrace and then copied it to the newly defined structure named regs using memcpy. For arguments refer above.

In the image shown above, we first freed some space in the target process and then the values of the fetched registers were set and then eip was set pointing to the address where code will be injected.

Snippet for the injectSharedLibrary():

In the above image:

ebx = address of malloc() in target process

edi = address of __libc_dlopen_mode() in target process

esi = address of free() in target process

ecx = size of the path to the shared library we want to load

In first block esi is decremented by 1,In the second asm() block the amount of memory is chosen, malloc is called and return address is saved in ebx.In the third asm() block, arguements are pushed to stack($1=RTLD_LAZY,ebx=Return Value) and then __libc_dlopen_mode()(libc’s implementation of dlopen()) is called. In the last asm() block, call to free is made.

In above blocks int $3 has been used to get back to the injector process.

Now once we got the functions resolved, registers set and address buffer, we will inject the library into the target process, for that we can use ptrace again:

In the above images, a new buffer is allocated, the injection library’s code gets copied to that new buffer,(memset: to fill the memory and memcpy: to copy the data), we have used injectSharedLibrary_size as argument and moreover as described above function’s code will get copied to newcode so that it can use them further along with RET(0xcc),at last we use Ptrace to perform our further tasks which involves mainly writing the data and continuing execution(similar to CreateRemoteThread in Windows). Now we can compile the code and see the result in the below image:

As you can see above while the target was running(on the left), the shared library named inlibrary.so got injected into the process of the target(right terminal) and the msg was printed.

This can be checked by attaching the target process in gdb as shown below:

This was a quick overview and idea that how a shared library can be injected into other running process in linux.In later blogs we will see other infection and injection techniques on LINUX platform so stay tuned😉.