Mukuyang'ana LD_PRELOAD

Cholemba ichi chinalembedwa mu 2014, koma ndinangoponderezedwa ndi Habré ndipo sizinawone kuwala kwa tsiku. Panthawi yoletsedwa ndinayiwala, koma tsopano ndinazipeza m'makalata. Ndinaganiza zochotsa, koma mwina zingakhale zothandiza kwa wina.

Mukuyang'ana LD_PRELOAD

Nthawi zambiri, kuwerengera pang'ono kwa Lachisanu pamutu wofufuza "kuphatikizidwa" LD_PRELOAD.

1. Kutuluka kwachidule kwa iwo omwe sadziwa za kusintha kwa ntchito

Ena onse akhoza kupita molunjika 2.

Tiyeni tiyambe ndi chitsanzo chapamwamba:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
  srand (time(NULL));
  for(int i=0; i<5; i++){
    printf ("%dn", rand()%100);
  }
}

Timapanga popanda mbendera iliyonse:

$ gcc ./ld_rand.c -o ld_rand

Ndipo, monga tikuyembekezeredwa, timapeza manambala 5 osasinthika osakwana 100:

$ ./ld_rand
53
93
48
57
20

Koma tiyerekeze kuti tilibe magwero a pulogalamuyo, koma tiyenera kusintha khalidwe.

Tiyeni tipange laibulale yathu yokhala ndi mawonekedwe athu, mwachitsanzo:

int rand(){
  return 42;
}

$ gcc -shared -fPIC ./o_rand.c -o ld_rand.so

Ndipo tsopano kusankha kwathu mwachisawawa ndikodziwikiratu:

# LD_PRELOAD=$PWD/ld_rand.so ./ld_rand
42
42
42
42
42

Chinyengochi chikuwoneka chochititsa chidwi kwambiri ngati titumiza kaye laibulale yathu kudzera

$ export LD_PRELOAD=$PWD/ld_rand.so

kapena tizichita kaye

# echo "$PWD/ld_rand.so" > /etc/ld.so.preload

ndiyeno yendetsani pulogalamuyo mwachizolowezi. Sitinasinthe mzere umodzi wa code mu pulogalamu yokha, koma machitidwe ake tsopano amadalira kachinthu kakang'ono ka mulaibulale yathu. Komanso, panthawi yolemba pulogalamuyi, a rand kunalibe nkomwe.

Zomwe zidapangitsa kuti pulogalamu yathu igwiritse ntchito zabodza rand? Tiyeni titenge sitepe ndi sitepe.
Ntchito ikayamba, malaibulale ena amayikidwa omwe amakhala ndi zofunikira ndi pulogalamuyi. Tikhoza kuwawona pogwiritsa ntchito Chidziwitso:

# ldd ./ld_rand
        linux-vdso.so.1 (0x00007ffc8b1f3000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe3da8af000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fe3daa7e000)

Mndandandawu ukhoza kusiyana kutengera mtundu wa OS, koma payenera kukhala fayilo pamenepo libc.so. Ndi laibulale iyi yomwe imapereka mafoni adongosolo ndi ntchito zoyambira monga lotseguka, malo, printf etc. Zathu rand alinso mwa iwo. Titsimikizire izi:

# nm -D /lib/x86_64-linux-gnu/libc.so.6 | grep " rand$"
000000000003aef0 T rand

Tiyeni tiwone ngati gulu la malaibulale likusintha likagwiritsidwa ntchito LD_PRELOAD

# LD_PRELOAD=$PWD/ld_rand.so ldd ./ld_rand
        linux-vdso.so.1 (0x00007ffea52ae000)
        /scripts/c/ldpreload/ld_rand.so (0x00007f690d3f9000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f690d230000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f690d405000)

Zikuoneka kuti variable yakhazikitsidwa LD_PRELOAD zimakakamiza kunyamula ld_rand.so ngakhale kuti pulogalamuyo sifunikira. Ndipo chifukwa cha ntchito yathu "randi" katundu kale kuposa rand от libc.so, ndiye amalamulira chisa.

Chabwino, takwanitsa kusintha ntchito yachibadwidwe, koma tingatsimikizire bwanji kuti ntchito yake yasungidwa ndipo zochita zina zikuwonjezedwa. Tiyeni tisinthe mwachisawawa:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
 
typedef int (*orig_rand_f_type)(void);
 
int rand()
{
  /* Выполняем некий код */
  printf("Evil injected coden");
  
  orig_rand_f_type orig_rand;
  orig_rand = (orig_rand_f_type)dlsym(RTLD_NEXT,"rand");
  return orig_rand();
}

Apa, monga "chowonjezera" chathu, timangosindikiza mzere umodzi wa malemba, pambuyo pake timapanga cholozera ku ntchito yoyambirira. rand. Kuti tipeze adilesi ya ntchitoyi tifunika dlsym ndi ntchito yochokera ku library libdlzomwe zidzapeza zathu rand mu mulu wa malaibulale amphamvu. Pambuyo pake tidzayitcha ntchitoyi ndikubwezera mtengo wake. Chifukwa chake, tiyenera kuwonjezera "-ldl" pa msonkhano:

$ gcc -ldl -shared -fPIC ./o_rand_evil.c -o ld_rand_evil.so

$ LD_PRELOAD=$PWD/ld_rand_evil.so ./ld_rand
Evil injected code
66
Evil injected code
28
Evil injected code
93
Evil injected code
93
Evil injected code
95

Ndipo pulogalamu yathu imagwiritsa ntchito "mbadwa" rand, atachitapo kale zinthu zonyansa.

2. Ululu wofufuza

Podziwa za chiwopsezo chomwe chingakhalepo, tikufuna kuzindikira kutsitsatu Izo zinachitidwa. Zikuwonekeratu kuti njira yabwino yodziwira ndikukankhira mu kernel, koma ndinali ndi chidwi ndi njira zodziwikiratu.

Kenako, mayankho ozindikirika ndi kutsutsa kwawo abwera awiriawiri.

2.1. Tiyeni tiyambe mophweka

Monga tanena kale, mutha kufotokozera laibulale kuti muyike pogwiritsa ntchito kusintha LD_PRELOAD kapena polemba mufayilo /etc/ld.so.preload. Tiyeni tipange zowunikira ziwiri zosavuta.

Choyamba ndikuwunika kusintha kwa chilengedwe:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

int main()
{
  char*  pGetenv = getenv("LD_PRELOAD");
  pGetenv != NULL ?
    printf("LD_PRELOAD (getenv) [+]n"):
    printf("LD_PRELOAD (getenv) [-]n");
}

Yachiwiri ndikuwunika ngati fayilo yatsegulidwa:

#include <stdio.h>
#include <fcntl.h>

int main()
{
  open("/etc/ld.so.preload", O_RDONLY) != -1 ?
    printf("LD_PRELOAD (open) [+]n"):
    printf("LD_PRELOAD (open) [-]n");
}

Tiyeni titengere malaibulale:

$ export LD_PRELOAD=$PWD/ld_rand.so
$ echo "$PWD/ld_rand.so" > /etc/ld.so.preload

$ ./detect_base_getenv
LD_PRELOAD (getenv) [+]
$ ./detect_base_open
LD_PRELOAD (open) [+]

Apa ndi pansipa, [+] akuwonetsa kuzindikira bwino.
Motero, [-] amatanthauza kulambalala kuzindikira.

Kodi chojambulira chotere chimagwira ntchito bwanji? Tiyeni tiwone kusinthika kwa chilengedwe kaye:

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>

char* (*orig_getenv)(const char *) = NULL;
char* getenv(const char *name)
{
    if(!orig_getenv) orig_getenv = dlsym(RTLD_NEXT, "getenv");
    if(strcmp(name, "LD_PRELOAD") == 0) return NULL;
    return orig_getenv(name);
}

$ gcc -shared -fpic -ldl ./ld_undetect_getenv.c -o ./ld_undetect_getenv.so
$ LD_PRELOAD=./ld_undetect_getenv.so ./detect_base_getenv
LD_PRELOAD (getenv) [-]

Mofananamo, timachotsa cheke lotseguka:

#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <errno.h>

int (*orig_open)(const char*, int oflag) = NULL;

int open(const char *path, int oflag, ...)
{
    char real_path[256];
    if(!orig_open) orig_open = dlsym(RTLD_NEXT, "open");
    realpath(path, real_path);
    if(strcmp(real_path, "/etc/ld.so.preload") == 0){
        errno = ENOENT;
        return -1;
    }
    return orig_open(path, oflag);
}

$ gcc -shared -fpic -ldl ./ld_undetect_open.c -o ./ld_undetect_open.so
$ LD_PRELOAD=./ld_undetect_open.so ./detect_base_open
LD_PRELOAD (open) [-]

Inde, njira zina zopezera fayilo zitha kugwiritsidwa ntchito pano, monga, tsegula64, stat etc., koma, kwenikweni, mizere yofanana ya 5-10 ndiyofunika kuti anyenge.

2.2. Tiyeni tipitirire

Pamwamba tidagwiritsa ntchito getenv () kupeza mtengo LD_PRELOAD, koma palinso njira "yotsika" yofikira ENV-zosintha. Sitidzagwiritsa ntchito ntchito zapakatikati, koma tidzatchula mndandanda **dziko, yomwe imasunga kopi ya chilengedwe:

#include <stdio.h>
#include <string.h>

extern char **environ;
int main(int argc, char **argv) {
  int i;
  char env[] = "LD_PRELOAD";
  if (environ != NULL)
    for (i = 0; environ[i] != NULL; i++)
    {
      char * pch;
      pch = strstr(environ[i],env);
      if(pch != NULL)
      {
        printf("LD_PRELOAD (**environ) [+]n");
        return 0;
      }
    }
  printf("LD_PRELOAD (**environ) [-]n");
  return 0;
}

Popeza apa tikuwerenga deta molunjika kuchokera pamtima, kuyitana koteroko sikungatheke, ndi zathu undetect_getv sichikusokonezanso kuzindikira kulowerera.

$ LD_PRELOAD=./ld_undetect_getenv.so ./detect_environ
LD_PRELOAD (**environ) [+]

Zikuwoneka kuti vutoli lathetsedwa? Zikungoyamba kumene.

Pulogalamuyo ikayamba, mtengo wakusintha LD_PRELOAD owononga safunikiranso kukumbukira, ndiko kuti, amatha kuwerenga ndikuchotsa asanapereke malangizo aliwonse. Zachidziwikire, kukonza mndandanda wazokumbukiridwa, pang'ono, ndi njira yoyipa yamapulogalamu, koma kodi izi zitha kuyimitsa munthu yemwe satifunira zabwino?

Kuti tichite izi tifunika kupanga ntchito yathu yabodza ine (), momwe timadumphira zomwe zidayikidwa LD_PRELOAD ndipo perekani ku linker yathu:

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
#include <stdlib.h>

extern char **environ;
char *evil_env;
int (*orig_execve)(const char *path, char *const argv[], char *const envp[]) = NULL;


// Создаём фейковую версию init
// которая будет вызвана при загрузке программы
// до выполнения каких-либо инструкций

void evil_init()
{
  // Сначала сохраним текущее значение LD_PRELOAD
  static const char *ldpreload = "LD_PRELOAD";
  int len = strlen(getenv(ldpreload));
  evil_env = (char*) malloc(len+1);
  strcpy(evil_env, getenv(ldpreload));

  int i;
  char env[] = "LD_PRELOAD";
  if (environ != NULL)
    for (i = 0; environ[i] != NULL; i++) {
      char * pch;
      pch = strstr(environ[i],env);
      if(pch != NULL) {
        // Избавляемся от текущего LD_PRELOAD
        unsetenv(env);
        break;
      }
    }
}

int execve(const char *path, char *const argv[], char *const envp[])
{
  int i = 0, j = 0, k = -1, ret = 0;
  char** new_env;
  if(!orig_execve) orig_execve = dlsym(RTLD_NEXT,"execve");

  // Проверям не существует ли других установленных LD_PRELOAD
  for(i = 0; envp[i]; i++){
    if(strstr(envp[i], "LD_PRELOAD")) k = i;
  }
  // Если LD_PRELOAD не было установлено до нас, то добавим его
  if(k == -1){
    k = i;
    i++;
  }
  // Создаём новое окружение
  new_env = (char**) malloc((i+1)*sizeof(char*));

  // Копируем старое окружение, за исключением LD_PRELOAD
  for(j = 0; j < i; j++) {
    // перезаписываем или создаём LD_PRELOAD
    if(j == k) {
      new_env[j] = (char*) malloc(256);
      strcpy(new_env[j], "LD_PRELOAD=");
      strcat(new_env[j], evil_env);
    }
    else new_env[j] = (char*) envp[j];
  }
  new_env[i] = NULL;
  ret = orig_execve(path, argv, new_env);
  free(new_env[k]);
  free(new_env);
  return ret;
}

Timapanga ndikuzindikira:

$ gcc -shared -fpic -ldl -Wl,-init,evil_init  ./ld_undetect_environ.c -o ./ld_undetect_environ.so
$ LD_PRELOAD=./ld_undetect_environ.so ./detect_environ
LD_PRELOAD (**environ) [-]

2.3. /proc/self/

Komabe, kukumbukira si malo otsiriza kumene mungapeze choloŵa m’malo LD_PRELOAD, palinso /proc/. Tiyeni tiyambe ndi zodziwikiratu /proc/{PID}/environ.

Ndipotu, pali njira yothetsera vutoli osazindikira **dziko и /proc/self/environ. Vuto ndilo khalidwe "lolakwika". unsetenv (env).

njira yolondola

void evil_init()
{
  // Сначала сохраним текущее значение LD_PRELOAD
  static const char *ldpreload = "LD_PRELOAD";
  int len = strlen(getenv(ldpreload));
  evil_env = (char*) malloc(len+1);
  strcpy(evil_env, getenv(ldpreload));
 
  int i;
  char env[] = "LD_PRELOAD";
  if (environ != NULL)
    for (i = 0; environ[i] != NULL; i++) {
      char * pch;
      pch = strstr(environ[i],env);
      if(pch != NULL) {
        // Избавляемся от текущего LD_PRELOAD 
        //unsetenv(env);
        // Вместо unset просто обнулим нашу переменную
        for(int j = 0; environ[i][j] != ' '; j++) environ[i][j] = ' ';
        break;
      }
    }
}
$ gcc -shared -fpic -ldl -Wl,-init,evil_init  ./ld_undetect_environ_2.c -o ./ld_undetect_environ_2.so
$ (LD_PRELOAD=./ld_undetect_environ_2.so cat /proc/self/environ; echo) | tr " 00" "n" | grep -F LD_PRELOAD
$

Koma tiyerekeze kuti sitinachipeze ndipo /proc/self/environ ili ndi "vuto" data.

Choyamba tiyeni tiyese ndi "disguise" wathu wakale:

$ (LD_PRELOAD=./ld_undetect_environ.so cat /proc/self/environ; echo) | tr " 00" "n" | grep -F LD_PRELOAD
LD_PRELOAD=./ld_undetect_environ.so

mphaka amagwiritsa ntchito zomwezo kuti atsegule fayilo tsegula (), kotero yankho ndilofanana ndi zomwe zidachitika kale mu gawo 2.1, koma tsopano tikupanga fayilo kwakanthawi komwe timakopera zikumbukiro zowona popanda mizere yomwe ili. LD_PRELOAD.

#define _GNU_SOURCE
#include <dlfcn.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>

#define BUFFER_SIZE 256

int (*orig_open)(const char*, int oflag) = NULL;
char *soname = "fakememory_preload.so";

char *sstrstr(char *str, const char *sub)
{
  int i, found;
  char *ptr;
  found = 0;
  for(ptr = str; *ptr != ' '; ptr++) {
    found = 1;
    for(i = 0; found == 1 && sub[i] != ' '; i++){
      if(sub[i] != ptr[i]) found = 0;
    }
    if(found == 1)
      break;
  }
  if(found == 0)
    return NULL;
  return ptr + i;
}

void fakeMaps(char *original_path, char *fake_path, char *pattern)
{
  int fd;
  char buffer[BUFFER_SIZE];
  int bytes = -1;
  int wbytes = -1;
  int k = 0;

  pid_t pid = getpid();

  int fh;
  if ((fh=orig_open(fake_path,O_CREAT|O_WRONLY))==-1) {
    printf("LD: Cannot open write-file [%s] (%d) (%s)n", fake_path, errno, strerror(errno));
    exit (42);
  }
  if((fd=orig_open(original_path, O_RDONLY))==-1) {
    printf("LD: Cannot open read-file.n");
    exit(42);
  }
  do
  {
    char t = 0;
    bytes = read(fd, &t, 1);
    buffer[k++] = t;
    //printf("%c", t);
    if(t == ' ') {
      //printf("n");
  
      if(!sstrstr(buffer, "LD_PRELOAD")) {
        if((wbytes = write(fh,buffer,k))==-1) {
          //printf("write errorn");
        }
        else {
          //printf("writed %dn", wbytes);
        }
      }
      k = 0;
    }
  }
  while(bytes != 0);
    
  close(fd);
  close(fh);
}

int open(const char *path, int oflag, ...)
{
  char real_path[PATH_MAX], proc_path[PATH_MAX], proc_path_0[PATH_MAX];
  pid_t pid = getpid();
  if(!orig_open)
  orig_open = dlsym(RTLD_NEXT, "open");
  realpath(path, real_path);
  snprintf(proc_path, PATH_MAX, "/proc/%d/environ", pid);
  
  if(strcmp(real_path, proc_path) == 0) {
    snprintf(proc_path, PATH_MAX, "/tmp/%d.fakemaps", pid);
    realpath(proc_path_0, proc_path);
    
    fakeMaps(real_path, proc_path, soname);
    return orig_open(proc_path, oflag);
  }
  return orig_open(path, oflag);
}

Ndipo gawo ili ladutsa:

$ (LD_PRELOAD=./ld_undetect_proc_environ.so cat /proc/self/environ; echo) | tr " 00" "n" | grep -F LD_PRELOAD
$

Malo otsatira odziwikiratu ndi /proc/self/maps. Palibe chifukwa chokhalira pa izo. Yankho lake ndilofanana kwambiri ndi lakale: koperani deta kuchokera pafayilo kuchotsa mizere pakati libc.so и ld.ndi.

2.4. Njira yochokera ku Chokepoint

Ndidakonda kwambiri yankholi chifukwa cha kuphweka kwake. Timafanizira ma adilesi a ntchito zomwe zakwezedwa mwachindunji kuchokera libc, ndi ma adilesi "NEXT".

#define _GNU_SOURCE

#include <stdio.h>
#include <dlfcn.h>

#define LIBC "/lib/x86_64-linux-gnu/libc.so.6"

int main(int argc, char *argv[]) {
  void *libc = dlopen(LIBC, RTLD_LAZY); // Open up libc directly
  char *syscall_open = "open";
  int i;
  void *(*libc_func)();
  void *(*next_func)();
  
  libc_func = dlsym(libc, syscall_open);
  next_func = dlsym(RTLD_NEXT, syscall_open);
  if (libc_func != next_func) {
    printf("LD_PRELOAD (syscall - %s) [+]n", syscall_open);
    printf("Libc address: %pn", libc_func);
    printf("Next address: %pn", next_func);
  }
  else {
    printf("LD_PRELOAD (syscall - %s) [-]n", syscall_open);
  }
  return 0;
}

Kutsegula laibulale podutsa "open ()" ndi cheke:

$ export LD_PRELOAD=$PWD/ld_undetect_open.so
$ ./detect_chokepoint
LD_PRELOAD (syscall - open) [+]
Libc address: 0x7fa86893b160
Next address: 0x7fa868a26135

Kutsutsa kudakhala kosavuta:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>

extern void * _dl_sym (void *, const char *, void *);
void * dlsym (void * handle, const char * symbol)
{
  return _dl_sym (handle, symbol, dlsym);
}

# LD_PRELOAD=./ld_undetect_chokepoint.so ./detect_chokepoint
LD_PRELOAD (syscall - open) [-]

2.5. Ma Syscalls

Zingawoneke ngati izi ndi zonse, koma tidzangoyendabe. Ngati tiwongolera kuyimba kwadongosolo ku kernel, izi zitha kudutsa njira yonse yolowera. Yankho lomwe lili pansipa ndiloti, limadalira zomangamanga (x86_64). Tiyeni tiyesetse kukhazikitsa kuti tipeze kutseguka ld.so.preload.

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>

#define BUFFER_SIZE 256

int syscall_open(char *path, long oflag)
{
    int fd = -1;
    __asm__ (
             "mov $2, %%rax;" // Open syscall number
             "mov %1, %%rdi;" // Address of our string
             "mov %2, %%rsi;" // Open mode
             "mov $0, %%rdx;" // No create mode
             "syscall;"       // Straight to ring0
             "mov %%eax, %0;" // Returned file descriptor
             :"=r" (fd)
             :"m" (path), "m" (oflag)
             :"rax", "rdi", "rsi", "rdx"
             );
    return fd;
 }
int main()
{
    syscall_open("/etc/ld.so.preload", O_RDONLY) > 0 ?
      printf("LD_PRELOAD (open syscall) [+]n"):
      printf("LD_PRELOAD (open syscall) [-]n");
        
}

$ ./detect_syscall
LD_PRELOAD (open syscall) [+]

Ndipo vutoli lili ndi yankho. Kadule kuchokera mwamuna'A:

ptrace ndi chida chomwe chimalola njira ya makolo kuyang'anira ndikuwongolera kupita kwa njira ina, kuwona ndikusintha deta yake ndi zolembetsa. Nthawi zambiri ntchitoyi imagwiritsidwa ntchito popanga ma breakpoint mu pulogalamu yowongolera ndikuwunika mafoni amtundu.

Njira ya makolo imatha kutsata poyitanira foloko (2), ndiyeno njira yamwanayo imatha kupanga PTRACE_TRACEME, kutsatiridwa (nthawi zambiri) pochita exec(3). Kumbali ina, njira ya makolo ikhoza kuyamba kukonza zomwe zilipo kale pogwiritsa ntchito PTRACE_ATTACH.

Potsata, njira ya mwana imayima nthawi iliyonse ikalandira chizindikiro, ngakhale chizindikirocho chimanyalanyazidwa. (Kupatulapo ndi SIGKILL, yomwe imagwira ntchito bwino.) Makolo adzadziwitsidwa za izi poyitana wait(2), pambuyo pake akhoza kuwona ndikusintha zomwe zili mu ndondomeko ya mwana isanayambe. Njira ya makolo imalola mwanayo kuti apitirize kuthamanga, nthawi zina kunyalanyaza chizindikiro chotumizidwa kwa icho kapena kutumiza chizindikiro china m'malo mwake).

Choncho, njira yothetsera vutoli ndikuyang'anira ndondomekoyi, kuimitsa isanayambe kuyitana kwadongosolo lililonse ndipo, ngati kuli kofunikira, kuwongolera ulusi ku ntchito ya mbedza.

#define _GNU_SOURCE
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/reg.h>
#include <sys/user.h>
#include <asm/unistd.h>


#if defined(__x86_64__)
#define REG_SYSCALL ORIG_RAX
#define REG_SP rsp
#define REG_IP rip 
#endif

long NOHOOK = 0;

long evil_open(const char *path, long oflag, long cflag) 
{
    char real_path[PATH_MAX], maps_path[PATH_MAX];
    long ret;
    pid_t pid;
    pid = getpid();
    realpath(path, real_path);
    if(strcmp(real_path, "/etc/ld.so.preload") == 0)
    {
        errno = ENOENT;
        ret = -1;
    }
    else
    {
        NOHOOK = 1; // Entering NOHOOK section
        ret = open(path, oflag, cflag);
    }
    // Exiting NOHOOK section
    NOHOOK = 0;
    return ret;
}

void init()
{
    pid_t program;
    // Форкаем дочерний процесс
    program = fork();
    if(program != 0) {
        int status;
        long syscall_nr;
        struct user_regs_struct regs;
        // Подключаемся к дочернему процессу
        if(ptrace(PTRACE_ATTACH, program) != 0) {
            printf("Failed to attach to the program.n");
            exit(1);
        }
        waitpid(program, &status, 0);
        // Отслеживаем только SYSCALLs
        ptrace(PTRACE_SETOPTIONS, program, 0, PTRACE_O_TRACESYSGOOD);
        while(1) {
            ptrace(PTRACE_SYSCALL, program, 0, 0);
            waitpid(program, &status, 0);
            if(WIFEXITED(status) || WIFSIGNALED(status)) break;
            else if(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP|0x80) {
                // Получаем номер системного вызова
                syscall_nr = ptrace(PTRACE_PEEKUSER, program, sizeof(long)*REG_SYSCALL);
                if(syscall_nr == __NR_open) {
                    // Читаем слово из памяти дочернего процесса
                    NOHOOK = ptrace(PTRACE_PEEKDATA, program, (void*)&NOHOOK);
                    // Перехватываем вызов
                    if(!NOHOOK) {
                        
                        // Копируем регистры дочернего процесса
                        // в переменную regs родительского
                        ptrace(PTRACE_GETREGS, program, 0, &regs);
                        // Push return address on the stack
                        regs.REG_SP -= sizeof(long);
                        // Копируем слово в память дочернего процесса
                        ptrace(PTRACE_POKEDATA, program, (void*)regs.REG_SP, regs.REG_IP);
                        // Устанавливаем RIP по адресу evil_open
                        regs.REG_IP = (unsigned long) evil_open;
                        // Записываем состояние регистров процесса
                        ptrace(PTRACE_SETREGS, program, 0, &regs);
                    }
                }
                ptrace(PTRACE_SYSCALL, program, 0, 0);
                waitpid(program, &status, 0);
            }
        }
        exit(0);
    }
    else {
        sleep(0);
    }
}

Kufufuza:

$ ./detect_syscall
LD_PRELOAD (open syscall) [+]
$ LD_PRELOAD=./ld_undetect_syscall.so ./detect_syscall
LD_PRELOAD (open syscall) [-]

+0-0=5

Zikomo kwambiri

Charles Hubain
Chokepoint
ValdikSS
Philippe Teuwen
derhass

, omwe nkhani zake, magwero ndi ndemanga zake zidachita zambiri kuposa zomwe ndidachita kuti izi ziwonekere pano.

Source: www.habr.com

Kuwonjezera ndemanga