Tirikutsvaga LD_PRELOAD

Ichi chinyorwa chakanyorwa muna 2014, asi ndakangouya pasi pekudzvinyirirwa paHabré uye haina kuona chiedza chezuva. Panguva yekurambidzwa ndakazvikanganwa, asi zvino ndakazviwana muzvinyorwa. Ndakafunga kuidzima, asi pamwe ichabatsira mumwe munhu.

Tirikutsvaga LD_PRELOAD

Kazhinji, zvishoma Chishanu admin kuverenga pamusoro penyaya yekutsvaga "inosanganisirwa" LD_PRELOAD.

1. Digression pfupi kune avo vasina kujairana nekutsiva basa

Vamwe vose vanogona kunanga p.2.

Ngatitange nemuenzaniso wekare:

#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);
  }
}

Isu tinogadzira pasina mireza:

$ gcc ./ld_rand.c -o ld_rand

Uye, sezvakatarisirwa, tinowana 5 nhamba dzisina kurongeka dzisingasviki zana:

$ ./ld_rand
53
93
48
57
20

Asi ngatimbofungidzira kuti isu hatina kodhi yekodhi yepurogiramu, asi tinofanira kuchinja maitiro.

Ngatigadzireiraibhurari yedu ine yedu basa prototype, semuenzaniso:

int rand(){
  return 42;
}

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

Uye ikozvino sarudzo yedu isina kurongeka inonyatso kufungidzira:

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

Uhu hunyengeri hunotaridzika zvakanyanya kushamisa kana tikatanga kutumira raibhurari yedu kuburikidza

$ export LD_PRELOAD=$PWD/ld_rand.so

kana kuti tichatanga kuzviita

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

uye wobva wamhanyisa chirongwa semazuva ese. Hatina kushandura mutsara mumwechete wekodhi muchirongwa chacho, asi maitiro ayo zvino anoenderana nebasa diki muraibhurari yedu. Uyezve, panguva yekunyora purogiramu, iyo randi akanga asipo.

Chii chakaita kuti chirongwa chedu chishandise manyepo randi? Ngatitore nhanho nhanho.
Kana application yatanga, mamwe maraibhurari anotakurwa ane mabasa anodiwa nechirongwa. Tinogona kuvaona tichishandisa ldd:

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

Rondedzero iyi inogona kusiyana zvichienderana neshanduro yeOS, asi panofanira kunge paine faira ipapo libc.so. Ndiyo raibhurari iyi inopa mafoni ehurongwa uye mabasa ekutanga akadai yakazaruka, malloc, kudhinda etc. Yedu randi ariwo pakati pavo. Ngative nechokwadi cheizvi:

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

Ngationei kana seti yemaraibhurari ichichinja kana yashandiswa 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)

Zvinoratidza kuti shanduko yaiswa LD_PRELOAD inomanikidza yedu kutakura ld_rand.so kunyange pasinei nokuti purogiramu pachayo haidi. Uye, kubva pabasa redu "randi" mitoro kare kupfuura randi от libc.so,anobva abata chigaro.

Zvakanaka, isu takakwanisa kutsiva basa rekuzvarwa, asi tingaite sei kuti tive nechokwadi chekuti kushanda kwayo kwakachengetedzwa uye zvimwe zviito zvinowedzerwa. Ngatigadzirise zvedu zvisina tsarukano:

#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();
}

Pano, se "wedzero" yedu, tinongodhinda mutsara mumwe chete wezvinyorwa, mushure mezvo tinogadzira chinongedzo chebasa rekutanga. randi. Kuti tiwane kero yebasa iri tinoda dlsym ibasa rinobva kuraibhurari libdlizvo zvichawana zvedu randi mumurwi wemaraibhurari ane simba. Mushure mezvo tichadaidza basa iri uye todzorera kukosha kwayo. Saizvozvo, isu tichafanira kuwedzera "-ldl" panguva yekusangana:

$ 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

Uye chirongwa chedu chinoshandisa "yekuzvarwa" randi, amboita zvinhu zvinonyadzisa.

2. Marwadzo ekutsvaga

Kuziva nezve njodzi inogona kuitika, tinoda kuona izvozvo preload Zvakaitwa. Zviripachena kuti nzira yakanakisa yekuona ndeyekuisundira mu kernel, asi ini ndaifarira sarudzo dzekuona muuserspace.

Zvadaro, mhinduro dzekuonekwa uye kuramba kwavo dzinouya dziri mbiri.

2.1. Ngatitange nyore

Sezvambotaurwa, unogona kutsanangura raibhurari kuti itakure uchishandisa shanduko LD_PRELOAD kana kuti nokuinyora mufaira /etc/ld.so.preload. Ngatigadzirei ma detectors maviri ari nyore.

Yekutanga ndeyekutarisa iyo set environment variable:

#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");
}

Yechipiri ndeyekutarisa kana faira rakavhurwa:

#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");
}

Ngatiisei mumaraibhurari:

$ 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) [+]

Pano ne pazasi, [+] inoratidza budiriro yakaonekwa.
Saizvozvo, [-] zvinoreva kudarika kuonekwa.

Ko detector yakadaro inoshanda sei? Ngatitarisei kusiyanisa kwezvakatipoteredza kutanga:

#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) [-]

Saizvozvowo, tinobvisa cheki yakazaruka:

#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) [-]

Ehe, dzimwe nzira dzekuwana faira dzinogona kushandiswa pano, senge, vhura64, Stat nezvimwewo, asi, chaizvoizvo, mitsara ye5-10 yekodhi inodiwa kuvanyengedza.

2.2. Ngatienderere mberi

Pamusoro takashandisa getenv() kuwana kukosha LD_PRELOAD, asi kunewo imwe nzira "yakaderera-yepamusoro" yekusvika ENV-siyana. Isu hatizoshandisa epakati mabasa, asi tichareva kune array ** nharaunda, iyo inochengeta kopi yezvakatipoteredza:

#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;
}

Sezvo pano isu tiri kuverenga data zvakananga kubva mundangariro, kufona kwakadaro hakugone kubatwa, uye yedu undetect_getenv hazvichavhiringidzi kuziva kupindira.

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

Zvinoita sekuti dambudziko iri ragadziriswa? Zvichiri kutanga.

Mushure mokunge purogiramu yatangwa, kukosha kwekusiyana LD_PRELOAD hackers havachaida mundangariro, ndiko kuti, vanogona kuiverenga nekuidzima vasati vaita chero mirairo. Ehe, kugadzirisa array mundangariro, padiki, yakashata dhizaini, asi izvi zvingamisa sei munhu asinganyatsotishuvire zvakanaka zvakadaro?

Kuti tiite izvi tinoda kugadzira yedu yekunyepedzera basa ini (), umo isu tinopindira yakaiswa LD_PRELOAD uye ipfuure kune yedu linker:

#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;
}

Isu tinotora uye tarisa:

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

Nekudaro, ndangariro haisi nzvimbo yekupedzisira kwaunogona kuwana inotsiva LD_PRELOAD, pane zvakare / proc /. Ngatitangei nezviri pachena /proc/{PID}/environ.

Muchokwadi, kune mhinduro yepasirese ye undetect ** nharaunda и /proc/self/environ. Dambudziko ndere "zvisizvo" maitiro unsetenv(env).

sarudzo yakarurama

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
$

Asi ngatimbofungidzira kuti hatina kuiwana uye /proc/self/environ ine "dambudziko" data.

Chekutanga ngatiedzei neyedu yapfuura "disguise":

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

katsi inoshandisa zvakafanana kuvhura faira vhura (), saka mhinduro yakafanana neyakatoitwa muchikamu 2.1, asi ikozvino tinogadzira faira renguva pfupi apo tinokopa kukosha kweyeuko yechokwadi pasina mitsara ine. 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);
}

Uye iyi nhanho yakapfuura:

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

Nzvimbo inotevera iri pachena /proc/self/maps. Hapana chikonzero chekugara pairi. Mhinduro yacho yakanyatsofanana neyakapfuura: kopira iyo data kubva pafaira bvisa mitsetse iri pakati libc.so и wdc.so.

2.4. Sarudzo kubva kuChokepoint

Ini ndainyanya kufarira mhinduro iyi nekuda kwekureruka kwayo. Isu tinoenzanisa kero dzemabasa akatakurwa zvakananga kubva libc, uye “NEXT” kero.

#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;
}

Kurodha raibhurari nepakati "vhura ()" uye tarisa:

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

Kuramba kwacho kwakazove nyore:

#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. Syscalls

Zvinoita sekunge izvi ndizvo zvese, asi isu tichakarukana. Kana tikatungamira iyo system yekufona yakananga kune kernel, izvi zvinodarika iyo yese yekubira maitiro. Mhinduro iri pazasi, hongu, inoenderana nekuvaka (x86_64) Ngatiedzei kuishandisa kuti tione pakavhurwa 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) [+]

Uye dambudziko iri rine mhinduro. Chidimbu kubva murume'A:

ptrace chishandiso chinobvumira maitiro emubereki kuona uye kudzora kufambira mberi kweimwe maitiro, kuona uye kushandura data rayo nemarejista. Kazhinji basa iri rinoshandiswa kugadzira mabreakpoints muchirongwa chedebugging uye kuona system mafoni.

Maitiro emubereki anogona kutanga kuteedzera nekutanga kudaidza forogo(2), uyezve inozoitika maitiro emwana anogona kuita PTRACE_TRACEME, inoteverwa (kazhinji) nekuita exec(3). Kune rimwe divi, maitiro emubereki anogona kutanga kugadzirisa maitiro aripo uchishandisa PTRACE_ATTACH.

Paunenge uchitsvaga, maitiro emwana anomira pese paanogashira chiratidzo, kunyangwe kana chiratidzo chisina kufuratirwa. (Kusiyapo ndekweSIGKILL, inoshanda zvakajairika.) Maitiro emubereki achaziviswa nezve izvi nekufonera wait(2), mushure mezvo anogona kuona nekugadzirisa zviri mukati megadziriro yemwana isati yatanga. Maitiro emubereki anobva abvumira mwana kuti arambe achimhanya, mune dzimwe nguva achiregeredza chiratidzo chakatumirwa kwairi kana kutumira imwe chiratidzo panzvimbo).

Nekudaro, mhinduro ndeyekutarisa maitiro, kuimisa isati yafona yega yega system uye, kana zvichidikanwa, tungamira tambo kune hoko basa.

#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);
    }
}

Tinotarisa:

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

+0-0=5

Kutenda kwazvo

Charles Hubain
Chokepoint
ValdikSS
Philippe Teuwen
derhass

, ane zvinyorwa, zvinyorwa uye zvirevo zvakaita zvakawanda kupfuura zvandakaita kuti chinyorwa ichi chioneke pano.

Source: www.habr.com

Voeg